[![CC 4.0][cc-image]][cc-url] [![NPM version][npm-image]][npm-url] [![Gitter][gitter-image]][gitter-url]
This document was written for those who want to learn Bash without diving in too deeply.
Tip: Try learnyoubash — an interactive workshopper based on this handbook!
You can install this handbook using npm. Just run:
$ npm install -g bash-handbook
You should be able to run bash-handbook at the command line now. This will open the manual in your selected $PAGER. Otherwise, you may continue reading on here.
The source is available here: https://github.com/denysdovhan/bash-handbook
Currently, there are these translations of bash-handbook:
if statementcase statementfor loopwhile loopuntil loopselect loopIf you are a developer, then you know the value of time. Optimizing your work process is one of the most important aspects of the job.
In that path towards efficiency and productivity, we are often posed with actions that must be repeated over and over again, like:
Enter Bash, our savior.
Bash is a Unix shell written by Brian Fox for the GNU Project as a free software replacement for the Bourne shell. It was released in 1989 and has been distributed as the Linux and macOS default shell for a long time.
So why do we need to learn something that was written more than 30 years ago? The answer is simple: this something is today one of the most powerful and portable tools for writing efficient scripts for all Unix-based systems. And that's why you should learn bash. Period.
In this handbook, I'm going to describe the most important concepts in bash with examples. I hope this compendium will be helpful to you.
The user bash shell can work in two modes - interactive and non-interactive.
If you are working on Ubuntu, you have seven virtual terminals available to you.
The desktop environment takes place in the seventh virtual terminal, so you can return to a friendly GUI
using the Ctrl-Alt-F7 keybinding.
You can open the shell using the Ctrl-Alt-F1 keybinding. After that, the familiar GUI will disappear and one of the virtual terminals will be shown.
If you see something like this, then you are working in interactive mode:
user@host:~$
Here you can enter a variety of Unix commands, such as ls, grep, cd, mkdir, rm and see the result of their execution.
We call this shell interactive because it interacts directly with the user.
Using a virtual terminal is not really convenient. For example, if you want to edit a document and execute another command at the same time, you are better off using virtual terminal emulators like:
In non-interactive mode, the shell reads commands from a file or a pipe and executes them. When the interpreter reaches the end of the file, the shell process terminates the session and returns to the parent process.
Use the following commands for running the shell in non-interactive mode:
sh /path/to/script.sh
bash /path/to/script.sh
In the example above, script.sh is just a regular text file that consists of commands the shell interpreter can evaluate and sh or bash is the shell's interpreter program. You can create script.sh using your preferred text editor (e.g. vim, nano, Sublime Text, Atom, etc).
You can also simplify invoking the script by making it an executable file using the chmod command:
chmod +x /path/to/script.sh
Additionally, the first line in the script must indicate which program it should use to run the file, like so:
#!/bin/bash
echo "Hello, world!"
Or if you prefer to use sh instead of bash, change #!/bin/bash to #!/bin/sh. This #! character sequence is known as the shebang. Now you can run the script like this:
/path/to/script.sh
A handy trick we used above is using echo to print text to the terminal screen.
Another way to use the shebang line is as follows:
#!/usr/bin/env bash
echo "Hello, world!"
The advantage of this shebang line is it will search for the program (in this case bash) based on the PATH environment variable. This is often preferred over the first method shown above, as the location of a program on a filesystem cannot always be assumed. This is also useful if the PATH variable on a system has been configured to point to an alternate version of the program. For instance, one might install a newer version of bash while preserving the original version and insert the location of the newer version into the PATH variable. The use of #!/bin/bash would result in using the original bash, while #!/usr/bin/env bash would make use of the newer version.
Every command returns an exit code (return status or exit status). A successful command always returns 0 (zero-code), and a command that has failed returns a non-zero value (error code). Failure codes must be positive integers between 1 and 255.
Another handy command we can use when writing a script is exit. This command is used to terminate the current execution and deliver an exit code to the shell. Running an exit code without any arguments, will terminate the running script and return the exit code of the last command executed before exit.
When a program terminates, the shell assigns its exit code to the $? environment variable. The $? variable is how we usually test whether a script has succeeded or not in its execution.
In the same way we can use exit to terminate a script, we can use the return command to exit a function and return an exit code to the caller. You can use exit inside a function too and this will exit the function and terminate the program.
Scripts may contain comments. Comments are special statements ignored by the shell interpreter. They begin with a # symbol and continue on to the end of the line.
For example:
#!/bin/bash
# This script will print your username.
whoami
Tip: Use comments to explain what your script does and why.
Like in most programming languages, you can also create variables in bash.
Bash knows no data types. Variables can contain only numbers or a string of one or more characters. There are three kinds of variables you can create: local variables, environment variables and variables as positional arguments.
Local variables are variables that exist only within a single script. They are inaccessible to other programs and scripts.
A local variable can be declared using = sign (as a rule, there should not be any spaces between a variable's name, = and its value) and its value can be retrieved using the $ sign. For example:
username="denysdovhan" # declare variable
echo $username # display value
unset username # delete variable
We can also declare a variable local to a single function using the local keyword. Doing so causes the variable to disappear when the function exits.
local local_var="I'm a local value"
Environment variables are variables accessible to any program or script running in current shell session. They are created just like local variables, but using the keyword export instead.
export GLOBAL_VAR="I'm a global variable"
There are a lot of global variables in bash. You will meet these variables fairly often, so here is a quick lookup table with the most practical ones:
| Variable | Description |
|---|---|
$HOME |
The current user's home directory. |
$PATH |
A colon-separated list of directories in which the shell looks for commands. |
$PWD |
The current working directory. |
$RANDOM |
Random integer between 0 and 32767. |
$UID |
The numeric, real user ID of the current user. |
$PS1 |
The primary prompt string. |
$PS2 |
The secondary prompt string. |
Follow this link to see an extended list of environment variables in Bash.
Positional parameters are variables allocated when a function is evaluated and are given positionally. The following table lists positional parameter variables and other special variables and their meanings when you are inside a function.
| Parameter | Description |
|---|---|
$0 |
Script's name. |
$1 … $9 |
The parameter list elements from 1 to 9. |
${10} … ${N} |
The parameter list elements from 10 to N. |
$* or $@ |
All positional parameters except $0. |
$# |
The number of parameters, not counting $0. |
$FUNCNAME |
The function name (has a value only inside a function). |
In the example below, the positional parameters will be $0='./script.sh', $1='foo' and $2='bar':
./script.sh foo bar
Variables may also have default values. We can define as such using the following syntax:
# if variables are empty, assign them default values
: ${VAR:='default'}
: ${$1:='first'}
# or
FOO=${FOO:-'default'}
Expansions are performed on the command line after it has been split into tokens. In other words, these expansions are a mechanism to calculate arithmetical operations, to save results of commands' executions and so on.
If you are interested, you can read more about shell expansions.
Brace expansion allows us to generate arbitrary strings. It's similar to filename expansion. For example:
echo beg{i,a,u}n # begin began begun
Also brace expansions may be used for creating ranges, which are iterated over in loops.
echo {0..5} # 0 1 2 3 4 5
echo {00..8..2} # 00 02 04 06 08
Command substitution allow us to evaluate a command and substitute its value into another command or variable assignment. Command substitution is performed when a command is enclosed by `` or $(). For example, we can use it as follows:
now=`date +%T`
# or
now=$(date +%T)
echo $now # 19:08:26
In bash we are free to do any arithmetical operations. But the expression must enclosed by $(( )) The format for arithmetic expansions is:
```ba
—
$ claude mcp add bash-handbook \
-- python -m otcore.mcp_server <graph>