58

On wikipedia, the article for .sh says:

For the .sh file extension type, see Bourne shell.

How about other unix shells?

I know that the shebang is used inside the file to indicate an interpreter for execution, but I wonder:

  • What are the pros and cons for files extensions vs no file extensions?
  • 4
    Sometimes, shell scripts without shebang (or without exec permissions) can be found. In that case, a name ending in .sh can be a hint to the user to run them with bash script.sh (or sh, of course). – Ansgar Esztermann Feb 15 '12 at 16:15
  • 3
    If a shell script has an extension it is commonly .sh. I have never seen a .ksh or .bash script. Most shell scripts have no extension though, like all the scripts in /etc/init.d/* as an example. – Richard Holloway Feb 15 '12 at 22:48
  • While a simplistic conclusion (yes or no) is opinion, the things to consider are not. – ctrl-alt-delor Oct 17 '19 at 19:36

7 Answers7

46

I would only call .sh something that is meant to be portable (and hopefully is portable).

Otherwise I think it's just better to hide the language. The careful reader will find it in the shebang line anyway. (In practice, .bash or .zsh, etc… suffixes are rarely used.)

  • 3
    From this page alone, we can already see quite a nontrivial amount of people using it. Why do you say they are "rarely used"? Any citations? Or is this merely based on your experience? – Pacerier Sep 15 '15 at 10:07
  • 1
    I would use .bash if it's meant to be sourced by another script and is only compatible with bash, etc. If it can be sourced by any bourne-compatible shell such as sh, dash, or bash, I would give it a .sh extension. If it's meant to be executed, I wouldn't put an extension. – Brandon Miller Jan 11 '21 at 17:19
  • 2
    I agree with hiding the language for executables, but I would elaborate that this isn't "just" better for not reason: it's very specifically better because putting the language in the executable name leaks an implementation detail into the interface! Why predict the future and say that your program will always be written as a shell script, or commit yourself to lying or breaking backwards compatibility if you ever have good reason to rewrite it in another language? – mtraceur Apr 17 '23 at 18:48
  • But I would assert that the best practice for libraries (files meant to be sourced by shells) is to say what shell it's meant to be sourced by in the extension, like @BrandonMiller said. Most people write sourceable files for just one shell, so for the common case that's trivial. Intentionally portable files can usually use the least featureful shell's name/extension (and in the very small corner case of for example supporting both bash and zsh but nothing else, you could just link/symlink/copy the file to both names, or put both extensions in the name). – mtraceur Apr 17 '23 at 18:52
29

I would say that no "good practices" for file extensions exist, strictly on a technicality: Unix/Linux/*BSD file systems don't support extensions per se. What you are calling an extension is merely a suffix of a single file name. That's different than the VM/CMS, VMS, MS-DOS and Windows file systems and OSes where a special spot in the inode-moral-equivalent is reserved for an extension.

That little rant now over, I think it's a bit silly to put a ".sh" or ".ksh" or ".bash" suffix on a shell script file name. A program is a program: no benefit exists in distinguishing what gets executed. No unix or linux or whatever kernel has decided to call an interpreter on some file just because of a file name suffix. It's all done by the #! line, or some other "magic number" sequence of bytes at the beginning of the file. In fact, deciding what to execute based on a file name "extension" is one of the factors that makes Windows a malware magnet. Look at how many Windows malware scams involve a file named "something.jpg.exe" - by default newer Windows don't show the ".exe" extension, and encourage a user to just double click on the "image". Instead of an image view running, the malware runs.

What you might think of as a straight-ahead command is often a shell script anyway. Sometimes cc has been a sh-script, firefox is an sh-script, startx is an sh-script. I don't believe there's a cognitive or organizational benefit to marking a script with a ".sh" suffix.

  • 37
    I disagree! My job consists of packaging an application involving thousands of files ranging from binary executables to shell scripts (ksh, bash and some legacy csh). To me, believe me it does make a difference to be able to know in a glance (or in a regex) what kind of file we are discussing and we are looking for. My point is that there could be a benefit in distinguishing what gets excuted and a best practice should encourage stating explicitly the type of file. – rahmu Feb 15 '12 at 16:31
  • 9
    @rahmu: write that up as an answer. Give some specifics about how regex-distinguishable names help you package (and maybe maintain) that application. Note specifically the interaction between what interprets the file and the file name's suffix and how that aids you in doing tasks. I'm interested in serious arguments against my viewpoint, and I'm willing to change if I'm convinced. I upvoted your comment to prove it. –  Feb 15 '12 at 16:57
  • 3
    I would love to, unfortunately I can only speak of my current experience in my current job. I don't know much about good practice and standards in general; I feel I should do some research before posting an answer here. I'll look into it tonight after work :) – rahmu Feb 15 '12 at 17:19
  • 3
    @rahmu The "file" command exists for determining file type. It is capable of distinguishing scripts written for different shells. – Matt Jun 18 '13 at 13:21
  • 1
    I allways makes ".sh" scripts to do complicated tasks. My basics scripts have no extension. – Emmanuel Apr 30 '14 at 16:08
  • 8
    If you give a shell script a .sh extension, you'll have to type that .sh as part of the command name when starting it. That's the main reason why I don't like putting that extension in (same with anything having a shebang line). BTW, the problem in Windows is not the .exe prefix per se (it's trivial to make an executable named image.jpg in Linux, after all), but the fact that Windows usually hides that extension, combined with the fact that the action needed to start an executable and to open a document is exactly the same. – celtschk Apr 30 '14 at 19:20
  • @BruceEdiger, You stated that file extension is one of the factors that make "Windows a malware magnet". But doesn't Linux have the equivalent vulnerability whereby hackers can insert #! or byte prefixes (as opposed to file name suffixes in Windows) to the file? For files that the user would chmod +x anyway, there's no way he would realize it. – Pacerier Sep 15 '15 at 10:11
  • @Pacerier - I don't understand your comment. But how many files do you chmod +x versus how many do you just open for read? That's the bad design in Windows "extensions" - you can easily be fooled into executing code, when you might believe you're just opening a file. –  Sep 15 '15 at 12:38
  • 1
    If you have an extension (postfix), and you change the implementation, then you have to change the file-name. And all scripts that call upon it. (a basic rule of programming: encapsulation, states that we should hide all implementation detail). – ctrl-alt-delor Oct 17 '19 at 19:30
  • @Pacerier and another reason that MS-Windows is a malware magnet is that all files have execute permission enabled by default. (there are others. I am not saying that these are the only reasons) – ctrl-alt-delor Oct 17 '19 at 19:33
16

As one who has worked in a multitude of ?nix environments, I have had to write in a wide variety of shells. Believe it or not, across platforms, the shells are not the same. So if you maintain your personal library in multiple shells (when necessary) it is very helpful to use extensions to ID the shells. That way when you move to another platform and the shell is slightly different, you know what scripts to target for modifications. .sh .ksh .bsh .csh ...

Jumpylodo
  • 161
  • 1
    This seems to agree with http://unix.stackexchange.com/questions/31760/file-extensions-for-unix-shell-scripts#comment43133_31761 – Pacerier Sep 15 '15 at 10:05
  • 2
    Do you not have a #! at the start of the script (e.g. #!/bin/bash)? – ctrl-alt-delor Jul 11 '19 at 08:06
  • 1
    Gnu/Linux, BSD, and the UNIXes are all Unix. No need for ?nix. Linux is a kernel, android used Linux but is not a Unix (unless you add extra software, in which case you have a Unix app). – ctrl-alt-delor Jul 11 '19 at 08:10
  • 1
    @ctrl-alt-delor: "Unix" is a trademark. People often use "?nix" to avoid the trademark issue (and the pedants). – JS. Oct 17 '19 at 16:51
  • 1
    @JS `UNIX' is a trademark of The Open Group. Unix and unix are not http://www.greens.org/about/unix.html – ctrl-alt-delor Oct 17 '19 at 19:22
  • @ctrl-alt-delor So only unix is all caps is trademarked. Good to know. Thanks! – JS. Oct 18 '19 at 00:31
10

You should not use an extension for executables, as they they are not interchangeable. Imagine that you have a shell script a.sh, then re-write in python a.py, you now have to change every program that calls you script, you have leaked implementation detail.

The whole file-name extension thing in Mircosoft's Windows is a mess: for example what could have been a.audio, b.audio, c.audio, is a.mp3, b.wav, c.ogg, and d.picture, e.picture, f.picture is d.jpeg, e.png, f.gif. Most of the time we do not care what format the audio or picture is in. We also have to spend a long time teaching new users all of the file extensions.

  • 2
    Another reason not to use *.sh I just ran into is that Debian's run-parts won't run scripts with extensions, such as in /etc/cron.*/: http://archive.oreilly.com/pub/post/runparts_scripts_a_note_about.html – Ross Patterson Aug 22 '16 at 20:42
6

As you said it, the Unix file extensions are purely information. You just need your script to have a correct shebang and being executable.

You can either have no extension or using .sh.

I personnaly use the following conventions, regardless of the shell used (csh, tcsh, bash, sh, ...):

  • no extension for system or high grade scripts (extremely rare).
  • the .sh for classic scripts, low to high grade.
Ouki
  • 5,962
  • 3
    What do you mean by "classic scripts, low to high grade"? – Pacerier Sep 15 '15 at 10:04
  • I think I meant abstraction or organisation level by that. That is you don't care what language/script tool is used behind some commands : so you don't use any extension. For others, it is good to known that it is a bash or some exotic ksh shell script (with the proper extension). ... but that was 2 years ago ;) – Ouki Sep 15 '15 at 11:59
4

Shell script extensions are quite useful. For example I often write scripts that have multiple files in multiple languages (eg. bash, awk and lua) in the same directory. If I need to search for a string in only the bash files, the extension makes this very handy, to reduce false positives. Or if I want to do a line count of all my bash code for that project.

It is a pain to have to type the extension when running the program, so I also make a symlink without the extension to the main executable, to edit/run it without needing to type the extension each time. Symlinks are cheap and easy.

Steve
  • 41
  • This seems to agree with http://unix.stackexchange.com/questions/31760/file-extensions-for-unix-shell-scripts#comment43133_31761 – Pacerier Sep 15 '15 at 10:06
2

As others have said, the shell doesn't care about extensions. However, it does allow for quick human identification of files. I see files ending in .py or .sh and I quickly know what they (at least) should be. As Steve says, searching by file extension or doing a line count are also practical considerations.

qwr
  • 709