Table of Contents
This chapter introduces you to shell expansion by taking a close look at commands and arguments. Knowing shell expansion is important because many commands on your Linux system are processed and most likely changed by the shell before they are executed.
The command line interface or shell used on most Linux systems is called bash, which stands for Bourne again shell. The bash shell incorporates features from sh (the original Bourne shell), csh (the C shell), and ksh (the Korn shell).
This chapter frequently uses the echo command to demonstrate shell features. The echo command is very simple: it echoes the input that it receives.
paul@laika:~$ echo Burtonville Burtonville paul@laika:~$ echo Smurfs are blue Smurfs are blue
One of the primary features of a shell is to perform a command line scan. When you enter a command at the shell's command prompt and press the enter key, then the shell will start scanning that line, cutting it up in arguments. While scanning the line, the shell may make many changes to the arguments you typed.
This process is called shell expansion. When the shell has finished scanning and modifying that line, then it will be executed.
Parts that are separated by one or more consecutive white spaces (or tabs) are considered separate arguments, any white space is removed. The first argument is the command to be executed, the other arguments are given to the command. The shell effectively cuts your command into one or more arguments.
This explains why the following four different command lines are the same after shell expansion.
[paul@RHELv4u3 ~]$ echo Hello World Hello World [paul@RHELv4u3 ~]$ echo Hello World Hello World [paul@RHELv4u3 ~]$ echo Hello World Hello World [paul@RHELv4u3 ~]$ echo Hello World Hello World
The echo command will display each argument it receives from the shell. The echo command will also add a new white space between the arguments it received.
You can prevent the removal of white spaces by quoting the spaces. The contents of the quoted string are considered as one argument. In the screenshot below the echo receives only one argument.
[paul@RHEL4b ~]$ echo 'A line with single quotes' A line with single quotes [paul@RHEL4b ~]$
You can also prevent the removal of white spaces by double quoting the spaces. Same as above, echo only receives one argument.
[paul@RHEL4b ~]$ echo "A line with double quotes" A line with double quotes [paul@RHEL4b ~]$
Later in this book, when discussing variables we will see important differences between single and double quotes.
Quoted lines can include special escaped characters recognised by the echo command (when using echo -e). The screenshot below shows how to use \n for a newline and \t for a tab (usually eight white spaces).
[paul@RHEL4b ~]$ echo -e "A line with \na newline" A line with a newline [paul@RHEL4b ~]$ echo -e 'A line with \na newline' A line with a newline [paul@RHEL4b ~]$ echo -e "A line with \ta tab" A line with a tab [paul@RHEL4b ~]$ echo -e 'A line with \ta tab' A line with a tab [paul@RHEL4b ~]$
The echo command can generate more than white spaces, tabs and newlines. Look in the man page for a list of options.
Not all commands are external to the shell, some are builtin. External commands are programs that have their own binary and reside somewhere in the file system. Many external commands are located in /bin or /sbin. Builtin commands are an integral part of the shell program itself.
To find out whether a command given to the shell will be executed as an external command or as a builtin command, use the type command.
paul@laika:~$ type cd cd is a shell builtin paul@laika:~$ type cat cat is /bin/cat
As you can see, the cd command is builtin and the cat command is external.
You can also use this command to show you whether the command is aliased or not.
paul@laika:~$ type ls ls is aliased to `ls --color=auto'
Some commands have both builtin and external versions. When one of these commands is executed, the builtin version takes priority. To run the external version, you must enter the full path to the command.
paul@laika:~$ type -a echo echo is a shell builtin echo is /bin/echo paul@laika:~$ /bin/echo Running the external echo command... Running the external echo command...
The which command will search for binaries in the $PATH environment variable (variables will be explained later). In the screenshot below, it is determined that cd is builtin, and ls, cp, rm, mv, mkdir, pwd, and which are external commands.
[root@RHEL4b ~]# which cp ls cd mkdir pwd /bin/cp /bin/ls /usr/bin/which: no cd in (/usr/kerberos/sbin:/usr/kerberos/bin:... /bin/mkdir /bin/pwd
The shell allows you to create aliases. Aliases are often used to create an easier to remember name for an existing command or to easily supply parameters.
[paul@RHELv4u3 ~]$ cat count.txt one two three [paul@RHELv4u3 ~]$ alias dog=tac [paul@RHELv4u3 ~]$ dog count.txt three two one
An alias can also be useful to abbreviate an existing command.
paul@laika:~$ alias ll='ls -lh --color=auto' paul@laika:~$ alias c='clear' paul@laika:~$
Aliases can be used to supply commands with default options. The example below shows how to set the -i option default when typing rm.
[paul@RHELv4u3 ~]$ rm -i winter.txt rm: remove regular file `winter.txt'? no [paul@RHELv4u3 ~]$ rm winter.txt [paul@RHELv4u3 ~]$ ls winter.txt ls: winter.txt: No such file or directory [paul@RHELv4u3 ~]$ touch winter.txt [paul@RHELv4u3 ~]$ alias rm='rm -i' [paul@RHELv4u3 ~]$ rm winter.txt rm: remove regular empty file `winter.txt'? no [paul@RHELv4u3 ~]$
Some distributions enable default aliases to protect users from accidentally erasing files ('rm -i', 'mv -i', 'cp -i')
You can provide one or more aliases as arguments to the alias command to get their definitions. Providing no arguments gives a complete list of current aliases.
paul@laika:~$ alias c ll alias c='clear' alias ll='ls -lh --color=auto'
You can display shell expansion with set -x, and stop displaying it with set +x. You might want to use this further on in this course, or when in doubt about exactly what the shell is doing with your command.
[paul@RHELv4u3 ~]$ set -x ++ echo -ne '\033]0;paul@RHELv4u3:~\007' [paul@RHELv4u3 ~]$ echo $USER + echo paul paul ++ echo -ne '\033]0;paul@RHELv4u3:~\007' [paul@RHELv4u3 ~]$ echo \$USER + echo '$USER' $USER ++ echo -ne '\033]0;paul@RHELv4u3:~\007' [paul@RHELv4u3 ~]$ set +x + set +x [paul@RHELv4u3 ~]$ echo $USER paul
1. How many arguments are in this line (not counting the command itself).
touch '/etc/cron/cron.allow' 'file 42.txt' "file 33.txt"
2. Is tac a shell builtin command ?
3. Is there an existing alias for rm ?
4. Read the man page of rm, make sure you understand the -i option of rm. Create and remove a file to test the -i option.
5. Execute: alias rm='rm -i' . Test your alias with a test file. Does this work as expected ?
6. List all current aliases.
7a. Create an alias called 'city' that echoes your hometown.
7b. Use your alias to test that it works.
8. Execute set -x to display shell expansion for every command.
9. Test the functionality of set -x by executing your city and rm aliases.
10 Execute set +x to stop displaying shell expansion.
11. Remove your city alias.
12. What is the location of the cat and the passwd commands ?
13. Explain the difference between the following commands:
echo
/bin/echo
14. Explain the difference between the following commands:
echo Hello
echo -n Hello
15. Display A B C with two spaces between B and C.
(optional)16. Complete the following command (do not use spaces) to display exactly the following output:
4+4 =8 10+14 =24
17. Use echo to display the following exactly:
??\\
Find two solutions with single quotes, two with double quotes and one without quotes (and say thank you to René and Darioush from Google for this extra).
18. Use one echo command to display three words on three lines.
1. How many arguments are in this line (not counting the command itself).
touch '/etc/cron/cron.allow' 'file 42.txt' "file 33.txt"
answer: three
2. Is tac a shell builtin command ?
type tac
3. Is there an existing alias for rm ?
alias rm
4. Read the man page of rm, make sure you understand the -i option of rm. Create and remove a file to test the -i option.
man rm
touch testfile
rm -i testfile
5. Execute: alias rm='rm -i' . Test your alias with a test file. Does this work as expected ?
touch testfile
rm testfile (should ask for confirmation)
6. List all current aliases.
alias
7a. Create an alias called 'city' that echoes your hometown.
alias city='echo Antwerp'
7b. Use your alias to test that it works.
city (it should display Antwerp)
8. Execute set -x to display shell expansion for every command.
set -x
9. Test the functionality of set -x by executing your city and rm aliases.
shell should display the resolved aliases and then execute the command: paul@deb503:~$ set -x paul@deb503:~$ city + echo antwerp antwerp
10 Execute set +x to stop displaying shell expansion.
set +x
11. Remove your city alias.
unalias city
12. What is the location of the cat and the passwd commands ?
which cat (probably /bin/cat)
which passwd (probably /usr/bin/passwd)
13. Explain the difference between the following commands:
echo
/bin/echo
The echo command will be interpreted by the shell as the built-in echo command. The /bin/echo command will make the shell execute the echo binary located in the /bin directory.
14. Explain the difference between the following commands:
echo Hello
echo -n Hello
The -n option of the echo command will prevent echo from echoing a trailing newline. echo Hello will echo six characters in total, echo -n hello only echoes five characters.
(The -n option might not work in the Korn shell.)
15. Display A B C with two spaces between B and C.
echo "A B C"
16. Complete the following command (do not use spaces) to display exactly the following output:
4+4 =8 10+14 =24
The solution is to use tabs with \t.
echo -e "4+4\t=8" ; echo -e "10+14\t=24"
17. Use echo to display the following exactly:
??\\ echo '??\\' echo -e '??\\\\' echo "??\\\\" echo -e "??\\\\\\" echo ??\\\\
Find two solutions with single quotes, two with double quotes and one without quotes (and say thank you to René and Darioush from Google for this extra).
18. Use one echo command to display three words on three lines.
echo -e "one \ntwo \nthree"