The Bash Special Characters You Should Know About

A photograph of a laptop screen with a shell script in display.

Not all characters are equal in Bash. Some of them carry out special functions, tweak commands, and help us manipulate data. That’s why we’ve compiled the following list with the most important Bash special characters. Read on to find out how to use them and how they can make your daily Bash life easier.

Folder Path Separator (/)

In Bash, the forward-slash (/)separates the parts of a path, the subfolders-within-folders. To visit the folder named “pictures” inside your home folder, you’ll have to use the command cd as:

cd /home/USERNAME/Pictures
A terminal showing the path separator character in action.

Everything after a forward slash in the above example resides within what precedes the slash.

Home Directory (~)

Instead of typing the full name of your home folder in your Bash terminal, you can use the tilde character (~). For example, to go to your home folder, use:

cd ~
A terminal showing the home directory character in a cd command.

You can also incorporate it into more complex paths. For example, to edit a file named “mydata.txt” inside the “Personal” folder in your Home directory, use:

nano ~/Personal/mydata.txt

Current / Above Folder (.)

You can use a single (.) or double dot (..)to define whether an action should be performed inside the current directory or the one above, respectively. A single dot (.) maps to the current folder while a double dot (..) maps to the folder above it.

Let’s say you’re in the folder “/home/USERNAME/Pictures” and want to execute the script called “transform_images.sh” within the same directory. In this case, type:

sh ./transform_images.sh

If, after executing the script, you want to return to the folder above the one you’re currently in, type:

cd ..

That would return you from the folder “/home/USERNAME/Pictures” to “/home/USERNAME.”

A terminal showing the directory movement using the double dot operator.

Comments and Cancels (#)

The hash symbol (#) is more useful when writing Bash scripts since it allows you to add comments to them for future reference. Bash ignores everything following a hash symbol.

In the following script, the first line defines it’s a Bash script, the second is a comment that’s ignored, and the third is a typical copy command:

#!/bin/bash
# This is a comment - you can type anything you want here
cp file1.txt /home/USERNAME/scripts/file2.txt
A terminal showing the comments on a bash script file.

Hashes are useful even if you’re not writing a script since they allow you to cancel parts of a command. To see that in action, try the following straightforward command:

echo I am YOUR_NAME

Then, try the following instead:

echo I am #YOUR_NAME

You’ll only see “I am” returned in the second version because the hash will have canceled everything that followed after.

Ranges ([])

You can define character ranges by enclosing them in brackets ([]). To see that in action, let’s say you want to look for folder names that start with either D or M. Type:

ls [DM]*
A terminal showing the contents of multiple directories.

Perhaps you’re in a folder filled with subfolders named after each year instead. To copy the folders for the previous five years into “/home/USERNAME/backup,” use:

cp -r 201[56789] /home/USERNAME/backup

You can even simplify them further with a dash (-):

cp 201[5-9] /home/USERNAME/backup

Bash will iterate from 5 to 9 to include the numbers between them.

Redirection (<>)

Using angle brackets (<>), you can redirect a command’s input or output. For example, the following command:

ls >> list.txt

will redirect the output of ls and save it to the “list.txt” file.

A terminal showing the shell append feature in bash.

Note that a double right-angle bracket (>>) appends a command’s output to a file. If you re-run the same command, it will append its output to the end of the existing content. To replace its content with new results, use a single right-angle brackets (>):

ls > list.txt
A terminal showing the replace feature in bash.

Pipes (|)

You can combine different commands into a larger whole to achieve more complex results by using pipes (|). They’re somewhat similar to redirection (more on their similarities and differences here).

Suppose you have a huge file with thousands of entries and want to locate your name in it. Instead of searching for it in a text editor, do the following:

cat entries.txt | grep 'YourName'
A terminal showing a simple pipe operator between cat and grep.

In this case, the output of “entries.txt” will be piped to the grep command.

Tip: Learn more about pipes, data streams and redirection by using sed in Linux.

Command Separator (;)

Bash allows you to issue multiple commands in one go by separating them with semicolons (;). For example, to copy two folders to two different destinations with one command:

cp -r folder1 destination1; cp -r folder2 destination2
A terminal showing a multi-command chain in bash.

The semicolon separates the two commands and tells Bash to execute them sequentially. Note that you can use more than two commands if you wish.

Wildcards (*)

You’ve probably already used the asterisk (*) in some commands. It matches any sequence of characters and allows actions like copying all JPG files from one folder to another:

cp /home/USERNAME/folder1/*.jpg /home/USERNAME/folder2/
A terminal showing a multi-file copy using shell wildcards.

The question mark (?) is also a wildcard in Bash but only matches a single character. For example:

cp /home/USERNAME/201?/*.jpg /home/USERNAME/folder2/
A terminal showing the multi-file copy across different directories.

The above command will copy all jpg files in folders that begin with “201.” Since the wildcard translates to any alphanumeric character, not only numbers, the above command would also copy any folder that might be named “201A” or “201z.”

Launch in Background (&)

You can run commands as background processes just by appending the command with an ampersand symbol (&):

cp /home/USERNAME/Downloads/huge_file.zip /home/USERNAME/backups &
A terminal showing a program running the background.

The above will start copying the file huge_file.zip and immediately move to the background, letting you keep using the terminal. The command will automatically exit when it completes. If you want to bring it forward again, you can do so by typing fg followed by Enter.

Variables ($)

The dollar sign ($) allows you to set up variables for use in your commands. To see them in action, try entering the following in your terminal:

myname=YOUR_NAME
myage=YOUR_AGE
echo "I'm $myname"
A terminal showing basic shell variables.

Note that there’s no dollar sign when assigning values to variables.

FYI: Bash variables can do more than just store static data. Learn how to create arrays and subshells inside shell variables.

Escapes (\) and Quotes (”)

If you want to use any of the special characters as it is in a command, you’ll have to escape it. You can do that by preceding the special character with a backslash (\). For example, if you have a file with a name that includes an exclamation mark, you’d have to type \! instead for Bash to interpret it as an exclamation mark and not as a special character.

A terminal showing the ls of a file with a funny name.

Another way would be using either single ('') or double-quotes (""). By enclosing a string in quotes, any special character in it will be treated as the actual character. There is a difference between single and double quotes, too. Single quotes will evaluate the enclosed string as text while double quotes allow you to use variables ($) within the enclosed string.

A terminal showing the difference between single quotes and double quotes.

Input (<) and Error (2>) Redirection

Aside from redirecting the output of programs, it is also possible to control where a program’s input comes from. The less-than (<) operator allows you to “pull” data out of files instead of “pushing” into them. For example, the following will remove all duplicate lines in the file “sort.txt” and sort them alphabetically:

uniq < sort.txt | sort
A terminal showing a simple input redirection command.

You can also force Bash to redirect any error messages from a program. The following code will redirect the output of the sort command on “out.txt” and the errors on “err.txt:”

sort ./invalid.file > out.txt 2> err.txt
A terminal showing a error redirection output from an invalid file.

Further, you can also use the ampersand (&) operator to combine the output of your program alongside any errors:

sort ./invalid.file &> out.txt
A terminal showing the output and error redirection from an invalid file.

Control Characters

A control character is an operator that allows you to include non-typeable characters inside your script. For example, the following will move the prompt one space down and one tab to the right:

printf "\v\t"
A terminal showing two different control characters.

Control characters can support features such as Unicode formatting. It does this by using the \x operator to interpret each byte value as a segment of a Unicode glyph.

The following code will print a null sign along with a delta character:

printf "\xe2\x88\x85 \xe2\x88\x86\n"
A terminal printing two Unicode characters using their hex codes.

Note: You can find the hex value of your Unicode glyph by piping it to the xxd utility:

printf "∅" | xxd
A terminal showing the hexdump of a Unicode character.

Arithmetic Expansion Character

The Arithmetic Expansion character is an operator that can do mathematical equations without any external programs. It works by treating anything inside the expansion as arguments for an integer calculation.

For example, the following line will add two numbers and print the result on the screen:

echo $(( 2 + 3 ))
A terminal showing a simple shell arithmetic command.

Further, you can also use variables inside any arithmetic expansion. The following code, for example, uses this as basis for a simple multiplication program:

#!/bin/bash
 
# Get the first ten multiples of a number.
for (( i = 1; i <= 10; i++ ));
do
    echo $(( $1 * $i ));
done
A terminal showing a simple multiples program using shell arithmetic characters.

Evaluation Character

The Evaluation character is a logical operator that helps you create test conditions inside your scripts. It contains the ability to detect files as well as variable inequalities:

#!/bin/bash
 
string1='Hello'
string2='World'
 
if [[ $string1 != $string2 ]];
then
    echo "The strings are not equal.";
fi
A terminal showing a simple shell evaluation character for two strings.

The following example also uses the evaluation character as a way to test whether the current directory contains a “maketecheasier” file:

#!/bin/bash
 
if [[ -e "maketecheasier" ]];
then
    echo "There is a file with the name maketecheasier";
fi
A terminal showing a simple file detection test using shell evaluation.

AND (&&) and OR (||) Characters

One of the downsides of the evaluation character is that it can only do a single test condition at any moment. To fix this, Bash provides two additional operators which extend the features of the evaluation character.

The AND character allows you to test two conditions and only return a value when both are true. For example, you can use it to make sure that a function will only run if it is in the right directory with the right file:

#!/bin/bash
 
target="/home/ramces/maketecheasier"
 
if [[ $target == $(pwd) && -e "maketecheasier.txt" ]];
then
    echo "Both conditions are true!"
fi
A terminal showing the AND operator between a subshell test and a file detection test.

Similar to AND, the OR character also allows you to test two conditions in a single evaluation. However, it will return a value even if only one of the conditions is true. The following example uses this to check for two similar directories:

#!/bin/bash
 
if [[ -d "directory1" || -d "directory2" ]];
then
    echo "A suitable directory exists!"
fi
A terminal showing the OR operator between two directory detection tests.

Subshell Execution and Grouping

A subshell is an independent shell process that you can run from inside the current session. Unlike a regular shell, a subshell will only open when you call it and it will close as soon as it resolves.

This approach prevents subshells from passing information between other shells. For example, the cat program in the following code will not find “test.txt” even if the subshell goes to the right directory:

( mkdir sample && cd sample && echo "Hello, MakeTechEasier" > test.txt ; ) && cat test.txt
A terminal showing a basic subshell command string.

Despite that, you can still “group” commands without creating a subshell. This can be helpful if you want to run commands under the current process:

{ mkdir sample && cd sample && echo "Hello, MakeTechEasier" > test.txt ; } && cat test.txt
A terminal showing a group shell execution string that does not create a new subshell.

Good to know: Modify your shell using your new Bash skills by customizing your .bashrc file.

Frequently Asked Questions

Is it possible to make a multi-line command in Bash?

Yes. You can do this by adding an escape character at the end of your command. This will move your cursor to the next line without running your program.

Can you get an earlier background program back to the foreground?

Yes. To do this, you need to run the jobs command and find the job number of the process that you want. Next, run fg followed by the number of your command to return it to the front.

Can you use an input and output redirection character in one command?

Yes. To do this, you need to provide your input redirection before your output. For example, running sed 2q < ./long-file > ./short-file will tell sed to read the “long-file” then output to the “short-file.”

Image credit: Xavier Cee via Unsplash. All alterations and screenshots by Ramces Red.

Subscribe to our newsletter!

Our latest tutorials delivered straight to your inbox

Ramces Red
Ramces Red - Staff Writer

Ramces is a technology writer that lived with computers all his life. A prolific reader and a student of Anthropology, he is an eccentric character that writes articles about Linux and anything *nix.