I have a bunch of hand-rolled executable scripts in my $HOME/bin directory. Some are written in bash, some in Ruby. All of them have the shebang line at the top telling the shell what interpreter to use (bash or Ruby, in my case).

I'm wondering if it is better to put file extensions on these scripts to indicate what scripting language they are written in? For example, the scripts in Ruby would have the *.rb suffix, and the bash ones would have the *.sh suffix.

Currently, these scripts just have simple names with no file extension.

What's the best practice?

  • 1
    It's easy enough to convert from shebang to extension and back with a simple script. So try one and fix it later if you need to. May 30, 2012 at 8:21

4 Answers 4


You can do wildcard commands like ls *.rb or cp *.sh if you want to organize your scripts in the future.

Start early or regret later, in my opinion.

Editors like vim will also be able to apply the correct syntax highlighting based on shebang or file extension.

This can also be accomplished by using modelines in various editors. E.g. for vim:

# vim: ft=sh
  • 2
    IMHO, organization is better done by function, not by details of implementation. Oct 7, 2011 at 17:09
  • 4
    @grawity: nevertheless is organizing by suffix simpler than grepping for shebang ...
    – akira
    Oct 7, 2011 at 17:30
  • Though I agree with the glob reason, most editors are smart enough to read the shebang to determine filetype. Sep 4, 2012 at 0:33

Well - as most things in life: It depends on your needs.

You stated that these scripts reside in a bin-directory and I assume that these scripts are to be called from the command line. As user I consider it as annoying if I have to type bla.ksh or foo.bash. Also if the coder decides to move to annother interpreter the command name would change too and I would have to amend other scripts that make use of these tools - very annoying, even if user and coder are the very same person.

But on the other hand I use extensions like .sh or .tcl in my project build directories. This way I can make use of make features to deploy the files into their destination directories - but at this stage I remove the file suffix.


Obviously there are some differences between executable files in bin directories, and editable "source" files.

  • For source files, it is helpful to have a suffix so you can see what is what, and to help some less-intelligent tools that fail to scan the #! line.
  • For modules, they're only used by a related set of programs, all of which use the same interpreter (or no interpreter), and it is conventional to include .pm, .sh or .so in such cases.
  • For executable programs, its name is part of the "programming contract" by which users and other scripts invoke it. It is important that the name does not change even if the implementation does; so obviously the filename should not have a suffix

In the case of a compiled program, the difference between "source" and "executable" is obvious: one contains source code, the other contains machine language or interpreted bytecode. In the case of a script, there's no obvious difference, but the make command maintains a notional separation between the "source code for a script" and the "executable version of a script": its default "compiler" for "shell script" is simply cp.

I would recommend keeping a separate $HOME/source directory, and either:

  • keeping a symlink, such as made by ln -s ../source/foo.sh $HOME/bin/foo; or
  • manually copy them after making changes (and testing them), using install -m 755 foo.sh ../bin/foo; or
  • using a Makefile rule to perform a syntax check before copying the source file from $HOME/source into $HOME/bin

Footnote: a shell script module is only usable by another shell script, and modifies the internal context of that script using the . or source built-in commands. This is different from an executable script, which (like any program) runs as a separate process and cannot modify its parent process. As a rough convention, modules go in /usr/lib/name_of_program/name_of_module.sh whereas commands go in /usr/bin/name_of_command (without any suffix).


It's not necessary. The kernel is already informed of the correct interpreter to use (by the #! line), and all popular text editors read it as well, so adding an extension would do nothing useful, only increase typing. The only time an executable program has an extension is when it is somehow important (to the program or the user or both).

Modules and libraries, on the other hand, almost always have extensions (.rb for Ruby modules, .so for ELF shared libraries, and so on).

  • the question is not so much about 'is the kernel able to run it if i dont provide the suffix' but about 'does it help ME'. increase of typed chars is irrelevant with completion.
    – akira
    Oct 7, 2011 at 17:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .