sh Command in Linux

Topics Covered

Overview

sh command in Linux is a command language interpreter that executes commands read from the terminal standard input, a .sh file in Linux, or some string from the command line.

In most modern systems, the sh command is symlinked to /bin/bash. Bash stands for Bourne Again Shell. It is one of the most popular shells in Linux. Bash was developed as a replacement for the T shell tcsh whose executable file had the name sh as well. Even though bash is a command interpreter, its main purpose was to be used as a shell scripting language.

Syntax of sh Command in Linux

Since the sh command in Linux is a command interpreter, we run it from a terminal emulator like Gnome Terminal or XTerm. The syntax for the sh command in Linux is:

Here, this command is used to the run sh file in Linux (which is a symlink to /bin/bash) which is then followed by flags that the user requires followed by the commands that the user wants to execute.

Since the sh command in Linux is usually symlinked to the bash shell, running sh --help on most modern Linux distributions returns the help prompt for the bash shell.

Running sh --help returns the bash help

As sh is a command interpreter, it can be used to run a .sh file in Linux. Let us take a look at how to run a sh script in Linux using the sh command:

We need to run a sh file in the following manner:

Running a sh script on Linux

Flags and Files

We can look at what flags the sh command in Linux supports by running sh -c "help set". We run this command since the sh command is symlinked to /bin/bash.

Running this command returns:

Let us take a look at some command line flags supported by sh:

  • -a: Mark variables which are modified or created for export.
  • -b: Notify of job termination immediately.
  • -e: Exit immediately if a command exits with a non-zero status.
  • --f: Disables globbing
  • -h: Remember the location of commands as they are looked up.
  • -m: Job control is enabled.
  • -n: Read commands but do not execute them.
  • -t: Exit after reading and executing one command.
  • -H: Enable '!' style history substitution. This flag is on by default when the shell is interactive.

We can also disable these flags by using + instead of - when interacting with the sh interpreter from the command line.

Files related to the sh command in Linux:

-** /bin/sh:** This file contains the sh interpreter. It is symlinked to /bin/bash in modern Linux distributions. Whenever we invoke the sh command in Linux, it invokes this file which in turn invokes /bin/bash.

  • /etc/profile: This file is used to set the system-wide environment variables. All system-wide environmental variables which are applied for all the users are set inside this file.

  • $HOME/.profile: This is a user-centric profile where the environmental variables that only affect the user are stored. Any environmental variables set inside this file are applicable only for the user who has set them and they do not affect the operations of other users.

  • **HOME/.bashprofile:ThisperformsthesamefunctionasHOME/.bash_profile:** This performs the same function as `HOME/.profile. The main difference between .bash_profileandHOME/.profileistheorderinwhichtheshcommandinLinuxsearchesforthesefiles.Theinterpreterfirstlooksfor/etc/profiletosetsystemwidevariablesfollowedbyHOME/.profile` is the order in which the sh command in Linux searches for these files. The interpreter first looks for `/etc/profile` to set system-wide variables followed by `HOME/.bash_profile. If this file is found, the interpreter sets the user variables and stops looking for $HOME/.profile`

  • $HOME/.bash_logout: This is an individual login shell cleanup file, which is executed when the login shell exits.

Parameters of sh Command in Linux

A parameter is an object or entity which stores something. A parameter can be anything, a number, string, or special characters. A variable in the sh command in Linux is a parameter that has a name associated with it. A variable has some value and can have some attributes assigned to it. These attributes are assigned to a variable using a shell built-in command called declare.

A variable is usually assigned in the form: 'name=value'. By default, values are null whenever no value is passed.

Whenever an assignment statement assigns a value to a shell variable or array index in the sh command in Linux, we can use the += operator to add or append to the variable's previous value. Whenever the += operator is used, the value is evaluated as an arithmetic expression and added to the variable's current value. This updated value is then also evaluated.

If the += operator is applied to an array variable using compound assignment, the variable's value is not unset and new values are added or appended at the next array index, that is, they are appended to a place greater than the maximum index of the array.

Whenever the += operator is applied to a string variable, the value is expanded and appended to the value of the variable.

Sh Command Substitution

Command substitution is a very useful feature of the sh command in Linux. Command substitution does what it means, it substitutes command.

We can substitute the standard output of a command and use it as a substitution in another string. This is called command substitution.

Command substitution is performed by enclosing the command we want to be substituted in a pair of grave accents (``). Trailing newlines are removed when using command substitution in the Linux sh command.

Let us see how to run the sh file in Linux with command substitution:

If we have a .sh file in Linux with the contents:

Then the script returns the name of the file itself. This is because the basename $0 in the script gets substituted to the actual standard output of the command, which is the name of the file itself.

Demonstrating command substitution

Sh Command Interpretations

Once the sh command in Linux performs functions like command substitution, it then scans the result of these substitutions for internal field separator characters which are found in the '$IFS' environmental variable. Newline, space, and tab are counted as internal field separator characters. If found, these are then split into distinct arguments where such characters are found. Null arguments and characters that are mentioned explicitly in the command like " or '' are left untouched. Any null arguments that are created implicitly due to substitution commands not producing any standard output responses are removed.

Generating File Names

Once all substitutions are performed by the sh command in Linux, either when we run a sh file in Linux or when we run a command in the shell, each command word is searched for the characters "*", "?" and "\[". If any one of these characters is found, then the word is treated as a pattern. The word is then replaced with alphabetically sorted file names that match the pattern. If the shell interpreter cannot find a file that matches the pattern, then the word is left unchanged. If the character "." appears at the beginning of a file immediately followed by "/" and the character "/" then in such a scenario, it must be matched explicitly.

Characters searched for during file name generation:

  • "*": Used to match any string, even null strings.
  • "?": Matches a single character.
  • [...]: Used to match any one of the enclosed characters. If a pair of characters are separated by "-" then it matches any character lexically between the pair of characters.
  • [!...]: Matches any character except the ones enclosed in the "[]".

Quoting and Prompting

Some characters have a special meaning in the sh command in Linux and cause the termination of a word unless they are enclosed in quotes. These characters are:

  • ;
  • &
  • (
  • )
  • |
  • ^
  • <
  • >
  • newline
  • space
  • tab

A character can be quoted or escaped by the use of '\\' before the special character.

Characters enclosed between a pair of quote marks ('') are quoted. Parameter and command substitution occur inside double quotes ("") and "\" quotes the character , ` and $.

Example of command termination

Prompting: When a shell is run interactively, it prompts with the value of '$PS1' before it reads a command. '$PS1' is an environmental variable that is used to specify the format of the command prompt displayed in the terminal when running the sh command in Linux. It stands for Prompt String 1. If a new line is entered and further input is required to complete a command, then a second prompt '$PS2' is used.

As '$PS1' is the prompt variable, the sh command in Linux, and by extension, bash allows us to customize its appearance by inserting several special backslash-escapes special characters and sequences that are decoded to dynamically display the prompt in the terminal. Some of these special characters and sequences are:

  • \a: ASCII bell character (07)
  • \h: The hostname is limited to the first appearance of '.'. For example, a hostname 'localhost. localdomain' would show up as 'localhost'.
  • \H: Prints the complete hostname of the system.
  • \n: The newline character
  • \l: The basename of the shell terminal's device name.
  • \s: The name of the shell. This is returned by basename $0.
  • \t: The current time in 24-hour format. The format for the time is: 'HH:MM: SS'.
  • \T: The current time in the 12-hour format. The time format is: 'HH:MM: SS'.
  • \A: The current time in 24-hour format with the display format being: 'HH: MM'.
  • @ The current time is in 12-hour format with the display format being: 'HH: MM'.
  • \u: The username for the current user.
  • \w: Returns the current working directory. the '$HOME' variable is denoted with the '~' (tilde) sign.
  • \W: Returns the basename of the current directory with the '$HOME' variable denoted with the '~' (tilde) sign.
  • $: When evaluating the prompt variable in the sh command in Linux, this returns the symbol '#' is the UID of the current user is '0', which denotes the root user. If the UID is anything other than '0', i.e., any user other than root then the '$' symbol is printed to the standard output.
  • ****: This effectively returns a single backslash to the standard output.
  • [: This escape sequence denotes the beginning of a sequence of non-printing characters, which can be used to embed terminal control sequence into the prompt.
  • ]: This denotes the end of a sequence of non-printing characters started by \[.

These are some of the most important and widely used escape sequences and special characters used in '$PS1'. These are evaluated and substituted for the '$PS1' variable when the sh command in Linux is run and a shell prompt is displayed.

Examples

Some examples involving the use of the sh command in Linux are:

  • sh: This command invokes binary symlinked to the sh command. In most cases, this is the bash shell. So, typing in sh in the terminal invokes the /bin/bash binary which drops us in a new shell.
  • sh filename.sh: We can use the sh command in Linux to run the sh file in Linux. It is always a good idea to start a .sh file in Linux with the shebang: #!/bin/sh. This way, whenever the .sh file is executed, it executes with the sh command which translates to its actual symlink. In most cases, this links to /bin/bash but it might be different in some distributions like Alpine Linux in which sh is symlinked to /bin/ash.
  • sh -e: We can have the sh command in Linux immediately exit if a command or .sh file in Linux returns a non-zero exit code.

Example: Running sh -e -c ls -la | grep file.txt will return exit code 1 if file.txt does not exist but it will return 0 if a file exists. This is demonstrated in the screenshot below:

Demonstrating the use of -e flag in sh

  • tcsh: Stands for TENEX C shell. It is a successor to the C shell with backward compatibility for the original C shell. This was popularly symlinked to the /bin/sh command in Linux before bash was released.
  • ksh: Another popular shell interpreter used in many BSDs.
  • pwd: A shell command that returns the present working directory when run from the terminal or when we run a .sh file in Linux with the help of the sh command in Linux.
  • ps: A shell command that reports and prints the resources used and the various processes using these resources. This is executed using the sh command in Linux.
  • init: The first program which is run in a system when the kernel finishes booting. It is responsible for starting other programs and services necessary for the system to become fully functional.
  • kill: A command which is used to send signals to other running processes. We can change the behavior of those processes or even terminate them with the kill command.

Conclusion

  • The h command in Linux is a command language interpreter that executes commands read from the terminal standard input, a file, or some string from the command line. Traditionally, it was symlinked to the tcsh shell but in most modern Linux distributions, it is symlinked to the bash shell which usually points to /bin/bash.
  • We can use the sh command in Linux to run the sh file in Linux by using the command: sh <filename>.sh.
  • The sh interpreter supports a lot of different flags to run commands and .sh files in Linux. Some of these flags are used when executing a command or running a .sh file in Linux.
  • The sh command in Linux also supports command substitution. We can substitute the result of a command from the standard output as a string in another command or a .sh file in Linux by placing the command in `` (grave accents).
  • Some characters hold special meaning and can cause character termination. These are used for quoting.
  • The sh command in Linux also supports a feature called prompting. Using prompting, we can set the terminal prompt in a shell using variables called '$PS1' which stands for Prompt String 1. This variable holds various escape sequences with special meanings which are used to display the terminal prompts.