You are on page 1of 13

Command Files in Linux

1. Interpreter Commands
A command transmitted to the interpretor has the format:
command_name arguments
Any executed command returns a number indicating the state of the command exit, zero for a
successfully executed command and nonzero in case of failure.
Several commands written on a line must be separated by ';'. The commands can be connected
through pipe (symbol '|'), such that the output for a command represents the input for the next.
In this case, the exit state is that of the last command of the pipe. For example, the command
"ls -l | less" applies the filter less on the result of the ls command. If the command sequence ends
with the character '&', they are executed asynchronously in the background and the identyfier
of the launched process is displayed. The continuation of a command on the next line is possible
if the line ends with the character '\'. The character sequence "&&" indicates the fact that the
execution of the following command will take place if the previous one was successfully
executed (AND type functionality). For an OR type functionality, the sequence "||" can be used.
The example below ilustrates the use of some of the described characters.
who | grep "labso" > /dev/null && \
echo "labso is logged on"
2. Variables
The variables recognized by the command interpreter can be: user variables, positional
parameters and predefined variables.
User Variables
Defining user variables is done like this:
name_var1=value
It is important to note that the command interpretor works with character strings, following that
both the variable name and its value are interpreted as strings. Therefore, in order to acces the
value of a variable, a special construction is needed, done by having the character '$' preceed
the variable name, like in the example below.
dir=/usr/student/adi
cd $dir
The user variables are evaluated at their value, unless that value is enclosed in quotes. The name
of a variable cannot be identical to that of an existing function. Marking the name of a variable,
when it is followed by another string - for example when we want to perform a concatenation
of the value of that variable with that string - is done by enclosing it between the characters '{ '
and ' }'. The example below illustrates this.
num=3
k=${num}tmp # k=$numtmp would have been
echo $k # interpreted as the variable numtmp
# Display 3tmp
The command interpretor offers a substitution mechanism based on the following rules:
 'character_string': characters within quotes are treated like regular character, without
any special meaning;
 "character_string": characters whithin inverted commas are treated like regular
characters, without any special significance, except the characters '$' and '\';
 \c: doesn't treat the character 'c' any different. In the strings eclosed within quotes, the
character '\' is meant to notify the interpretor not to treat treat differently the characters
in the set {$, `, " ,\};
 var=`command`: has as effect the execution of the command eclosed in '`' (inverted quote)
and the assigning of its output to the variable. For example, "rep=`pwd`" assignes to the
variable the result of the command pwd.
Concerning the variables defined within a command interpreter, one needs to know they form
a distinct set for each instance (process) of the interpretor, even if two variables with the same
name are used in both instances of the interpretor. This stands both in the case of two users,
who inside their own instances of the interpretor define variables with the same name, and when
a user executes command files in the context of an interpretor, variables with the same name
being used both inside the interpretor and inside the command file. The image below illustrates
this fact through the sequence of input commands.

We notice in the context of the interpretor the variable x is assigned the value 100, value that is
not modified (to 50) by the execution of the command file. The explanation is that the execution
of the commands in the file fis_cmd is done in the context of a new instance (process) of the
interpretor, that is launched by the initial one, each process having its own set of variables. In
order to make known a variable to an instance that has been launched subsequently by the
interpretor, the command export is used. The example below illustrates this fact.

Positional Parameters
Positional parameters, denoted by $1, $2, $3, ... represent the means of accessing the arguments
transmitted to a command file in the command line. The variable $0 is the name of the executed
command file.
Predefined and Special Variables
There is a series of predefined variables, initialized at the entry in the system and used by the
interpretor or other applications. Some of them are:
$HOME
Denotes the directory in which an instance of the interpretor, belonging to a user, is positioned
at the moment of the user's entry in the system. The value of this variable is used as implicit
directory argument for the command cd.
$PATH
Defines the list of directories the interpretor has visited in the search for an executable file
corresponding to the input command (directories are separated by the character ':').
$UID
Indicates the identifier of the user on whose account the command interpretor is executed.
$USER
Indicates the name of the user on whose account the command interpretor is executed.
$SHELL
Indicates the name of the current interpretor.
Special variables are described below. Their value cannot be modified.
 $# - the number of arguments in the command line (excluding $0);
 $*, $@ - list of positional parameters;
 $? - exit state of the last executed command;
 $$ - process identifier associated to the interpretor;
 $! - identifier of the last process launched in the background
3. Command Files
One of the main facilities made available by the interpretor is the posssibility of creating
procedures out of operating system commands. This allows for the execution of command files,
treated as procedures. The call for such a procedure is identical to that for a command:
procedure arg1 arg2 ... argn
The procedure corresponds to the name of a command file, for which the executable right is
set. Otherwise, the procedure and its parameters must be specified as arguments of another
interpretor, having the form:
interpretor_name procedure arg1 arg2 ... argn
The transmitting of a procedure's arguments is done by value. Remember that the execution of
the commands in the file is done in the context of another instance of the interpretor, this being
a child process of the interpretor. Command files can be called recursively.
3.1. Linux Commands
This type of commands are programs which appear as executable files and are, as a rule, found
in one of the directories /bin, /sbin, /usr/bin, /usr/sbin or other, directories included in
the value of the variable PATH. We give a brief description of some of them below.
man [manual_section] command_name
Displays the manual page containing information about the specified command. The section
of the manual containing the command can be specified optionally.
cp source_file destination_file
cp source_file_list destination_directory
Copy a file under another name, or several files into a directory.
mv source_file destination_file
mv source_file_list destination_directory
Rename a file or move several files to a directory.
rm file_or_directory
Remove a file or directory.
mkdir directory_name
Create a directory.
cat file_list
Displays on the screen the content of the files given as arguments.
test condition
Evaluate the condition and return its result. This command is used in the case of control
structures that need to evaluate a condition (such as IF). The condition may appear in
one of the forms below:
! condition
negate the result of the evaluation of the expresion
cond1 -a cond2
realize an evaluation like a logical AND
-n character_string
True if the string has a nonzero length.
-z character_string
True if the string has length zero.
character_string1 = character_string2
True if the strings are identical.
character_string1 != character_string2
True if the strings are different.
nr1 -eq nr2
True if the two integers are equal. Other comparison options are: -lt (less than),
-le (less than or equal), -gt (greater than), -ge (greater than or equal).
-d directory_name
True if the specified directory exists.
-f file
True if the specified file exists and is a normal file.
This command is found among those contained in the loader's code (codul
încărcătorului.)
less text_file
Allows, among other things, the display on the screen of a text file, page by page. Also allows
the scrolling back and forth of the visualization.
uname -a
Displays information about the system.
pwd
Displays the current directory of the shell instance where the command has been
launched.
3.2. Functions and Commands Contained by the Interpretor
Functions can be defined inside command files. The general format for defining a function is:
function_name()
{ cmd1; ... cmd2; }
where function_name is the name of the function, the parenthesis mark the definition of the
function, and the function body is specified inside the curly brackets. The first command must
be separated from the open curly bracket by a blank and the last command is followed by the
character ';', if the close curly bracket is on the same line as the command. Usually, if a user has
defined more functions inside a file, he can make the shell aware of them by specifying the file
name, preceded by a point and a blank, in the command line:
. myfuncs

The execution of a function is faster than that of the equivalent command file, because the
interpretor doesn't need to locate the file on the disk, open it, and load its content in the memory.
Deleting a function definition is similar to deleting a variable. The command unset is used.
The commands incorporated by the interpretor can be called directly in the command files.
Some of them, and their effect are presented below.

break [n]
Is the command for leaving the innermost for, while or until loop. If n is specified, n loops
are exited. For example:
while true
do
cmd=`getcmd`
if [ "$cmd" = quit ]
then break
else processcmd "$cmd"
fi
done
cd [dir]
Changes the current directory to the specified one. The current directory is part of the current
context. Because of this, at the execution of the command cd in a subinstance of the
interpretor, only the current directory is modified.

continue [n]
Is the command that allows the proceeding to a new iteration of the for, while or until loop.
For example:

for file
do
if [ ! -f "$file" ]0
then
echo "$file not found"
continue
fi
# operations on file
done
echo [-n][arg]
Is the command for displaying its arguments (words) at the standard output. If the option -n
is specified, the character '\n' is not written at the standard output.

eval cmd
Evaluates a command and executes it. For example:

One notices that eval passes through the argument list twice: at the transmitting of the
arguments to eval and at the executing of the command. This is illustrated by the following
example.
The eval command is used in command files that build command lines out of several
variables. The command is useful if the variables contain characters that have to be
recognized by the interpretor not as result of a substitution. Such characters are: {;, |, &, < ,
>, "}.
exec prg
Executes the specified program, prg. The launched program replaces the current one. If exec
has as argument the redirecting I/E, will have I/E redirected. For example:

file=$1 # counts the number


count=0 # of lines in a file
exec < $file
while read line
do
count=`expr $count + 1`
done
echo $count

exit [(n)]
Causes the termination of the current interpretor with the exit code equal to n. If n is omitted,
the exit code is that of the last executed command.
export [v...]
Marks v as exported variable name for the subsequently executed commands. If no argument
is specified, a list with all the names exported by the current interpretor is displayed.
Functions cannot be exported.
getopts opt v
The command is used to modify the options in the command line. It is usually executed in
loops. In every iteration getopts inspects the next argument in the command line and decides
whether it is a valid option or not. The decision requires every option begin with the character
'-' and be followed by a letter specified in opt. If the option exists and is correctly specified,
it is stored in the variable v and the command returns zero. If the letter is not amog those
specified as options in opt, the command stores a question mark in v and returns zero along
with displaying an error message at the error standard. If the arguments in the command line
have been exhausted or the next argument doesn't begin with the character '-' the command
returns a value different from zero. For example, for getopts to recognize the options "-a"
and "-b" for a command cmd, the call is:
getopts ab var
The command cmd can be called:
cmd -a -b or cmd -ab

In case the option calls for a suplimentary argument, this has to be separated from the option
by a blank. In order to indicate to the getopts command that an argument follows after an
option, the letter of the option must be postfixed by the character ':'. For example, if the option
"-b", in the previous example needed an argument, then it must be written:
getopts ab: var
If getopts doesn't find the argument after the option "-b", a question mark is stored in the
variable var and an error message is displayed at the standard output. If the argument exists,
it is stored in a special variable, OPTARG. Another special variable, OPTIND, is used by the
command to specify the number of processed arguments. Its initial value is 1.

read variable_name_list
A line is read from the standard input file, and the specified variables are assigned the value
of the read words. For example:

readonly [v...]
Identical with read, but the value of the variable v cannot be changed by future assignments.
If the argument is missing, read-only variables are displayed.
return [n]
Allows the return from a function with the value n. If n is omitted, the code returned is that
of the last executed command. The returned value can be accessed through the variable $?
and can be tested in the if, while and until control structures. For example:
shift [n]
Shift to the left (by n) of the parameters in the command line.
sleep n
Suspend the execution for n seconds.
[ condition ]
The command is equivalent to test condition.

type cmds
Supplies information about the specified command or commands. The information specifies
if the command is: a function defined by the user, one internal to the interpretor, or a Linux
command under the form of an executable.
unset v
Allows the deletion of a variable value from the current environment.

3.3. Control Structures


After the execution of a command a code is returned, which can be tested in the conditional
control structues. A correctly executed command returns the code zero.
A command pipe is a sequence of one or more commands separated by the character '|'. The
output of one serves as input for the next. Each command is a separate process, the interpretor
waiting for the execution of the last command in the pipe. The state of a pipe is the state of the
last command in the pipe. A list is a sequence of one or more commands separated by the
characters ';', '&' or "&&" and "||". Separators afect the execution this way:
 ';' - sequential execution;
 '&' - asynchronous execution (background);
 "&&" - executes the next command if the predeceeding one has returned 0;
 "||" - identic with "&&", but the exit state different from 0.

The commands that allow the control of future execution based on the evaluation of a condition,
are part of the commands implemented inside the interpretor. They are described below.

IF Command
The syntax of the command is:
if cond1
then cmd_list1
[ elif cond2
then cmd_list2]
[ else cmd_list3]
fi

The example below ilustrates the use of the command.

if test -f $1
then echo $1 is a regular file
elif test -d $1
then echo $1 is a directory
else echo $1 is unknown
fi

It is possible to write the if command on a single line, but in this case the conditions and
commands preceeding key words must end in ';'. The example above may be written:

if test -f $1; then echo $1 is a regular file


elif test -d $1; then echo $1 is a directory
else echo $1 is unknown; fi

CASE Command
The command syntax is:

case expression in
pattern_1) list;;
pattern_2) list;;
...
esac
expression is compared to each of the present patterns and the command list corresponding to
the match is executed. For example, the analysis of an option in the command line can be done
as follows:
case $1 in
-r) echo option r;;
-m) echo option m;;
*) ;;
esac

FOR Command
The command syntax is:
for name [in word_list]
do
command_list
done
The loop variable name takes in turn the values in the word list. For each value the for loop is
executed. If the word list is not specified (an neither is the key word in), the for loop is executed
for each argument transmitted in the command line. The condition can also be specified in the
form
"for in pattern", where pattern is a string of characters containing the character '*', in which
case the variable name is assigned the name of the files and subdirectories matching the given
pattern. The example below is equivalent with the execution of the command "ls
/home/student/*.c".

for fis in /home/student/*.c


do
echo $fis
done

WHILE Command
The command syntax is:

while condition
do
command_list
done

If the exit state from the last command in condition is zero, the command list is executed.
Otherwise, the loop ends. For example, in order to periodicaly test if a person is present, the
following sequence can be used:
while ;
do
if who | grep $1 /dev/null
then echo $1 is present
exit
else
sleep 120
done

UNTIL Command
The command is simillar to WHILE. Its syntax is:
until condition
do
command_list
done
3.4. Redirecting Standard Files
The operating system automatically opens three files for each newly created process (having
the descriptors 0,1,2), corresponding to the input, output and standard error output. The
interpretor allows the redirecting of the standard input/output files towards other devices or
files.
command < file_name
The file file_name is associated to the standard input. Therefore, all read operations that
required an input from the keyboard are done from the specified file.
command > file_name
The file file_name is associated to the standard output. All writing operations that had
as effect a display on the screen are done to the specified file.
command >> file_name
Simillar to the construction above, but the file is appended to, so its previous content is not
used.
command > &nr
Indicates the fact that the open file having as descriptor nr is associated to the standard
output. Asssumes the knowledge of the descriptor of an open file, and is therefore used
to indicate the redirecting of the error output to the same file as the standard output, or
the other way around. For example:
ls > fis 2>&1
Examples:
cat fis > /dev/lp
List the file at the printer;
cat f1 f2 > f3
Concatenate files f1 and f2 in f3. If f3 already exists, by redirecting with '>' its old content
is lost.
cat f1 f2 >> f3
If f3 already exists, to its old content the result of concatenating f1 and f2 is added.
4. Examples of Command Files
Example 1
The command file below creates a file of records containing person names:
valid()
{
case $1 in
f[3-5][1-6][1-6][1-6]);;
*) echo > invalid;;
esac
}
echo Create file
echo File name having the form fnnn:
read fname
valid $fname
if test -f invalid
then
echo Invalid name
rm invalid
exit
fi
echo > $fname
aux=0
echo Input the records:
while read string
case $string in
[a-zA-Z]*);;
*) aux=1;;
esac
test $aux -eq 0
do
echo $string >> $fname
done
sort $fname -o $fname
echo The created file:
echo
cat $fname
Example 2
The following command file lists all the files in the directory received as argument in the
command line, including its subdirectories.

The command file is called ls_rec.sh and is called like this:


./ls_rec /home/student
The content of the command file ls_rec.sh is:
echo
echo Directory $1
if test -d $1
then
for name in $1/.[a-z,A-Z]* $1/*
do
if test -d $name
then
./ls_rec $name
elif test -f $name
then echo $name
fi
done
fi
5. Problems
1. Check what the following command sequences display:
a. eval echo \$$#
b. x=100
px=x
eval echo \$$px
eval $px=5
echo $x
c. ls -R / >fis 2>fis_err
d. exec ls
e. exec 2>/tmp/err
f. (inside a command file)
file=$1
count=0
while read line
do
count=`expr $count + 1`
done < $file
echo $count

Note that the example at point g is the content of a command file where the while loop is
executed in another instance of the interpretor because its input is redirected towards $file.
2. Explain the effect of the following commands:
who | wc -l > fis
ls *.c | wc -l >> fis
who | sort
3. Write a command file named recho.sh, which displays its arguments in reverse order
a. on the same line
b. on different lines (the eval command can be used).
4. The command file below decides if two directories are identical from the point of view of
the content of the files ending in ".c", but contains a few errors. What are they?

crtdir=`pwd`
if [ -d $1 ]
then
if [ -d $2 ]
then
cd $1
ls -R > $crtdir/f1
cd $crtdir
cd $2
ls -R > $crtdir/f2
cd $crtdir
grep '.c$' f1 > f11 # only the ".c" files
grep '.c$' f2 > f22 # remain, alphabetically
rm f1 f2 # ordered
if cmp f11 f22
then
echo "Equal directories"
else
echo "Different directories"
fi
rm f11 f22
else
echo "$2 not a directory"
fi
else
echo "$1 not a directory"
fi
5. Write a command file that checks whether two directories are equal, without using the
command ls. The names of the two directories are transmitted as arguments in the command
line. Two directories are considered equal if the trees rooted in them are identical from the
point of view of the structure, and their corresponding nodes have the same name.
6. Write a command file that allows the search for a file in the entire structure of a
subdirectory, without using the command find or other commands simillar to it. The
arguments are given in the command line.
7. Write a command file that deletes all C source files from a directory, if their names are
found in the structure of another directory. The first argument in the command line is the
directory where the C source files are located, and the second is the directory where the
search begins.
8. Write a command file that copies the entire structure of a directory as structure in another
directory. The two directories are given as arguments in the command line.
9. Compute, using the command ls, the number of files and directories in a directory, taking
into account the entire structure of the tree rooted in the given directory. The name of the
directory is given as argument in the command line.
10. Write a command file that computes the number of files, directories and symbolic links in
a directory, taking into account the entire structure of the tree rooted in the given directory.
Display the same information for all the visited subdirectories. The name of the directory is
given in the command line.
11. Write a command file that creates a directory whose path is specified as argument in the
command line, and in that directory create files named for the users logged on at that
moment.
12. Write a command file that computes the total number of text lines and the number of words
in all the files in a directory, taking into account the entire structure of the tree rooted in that
directory.
13. Write a command file that executes in a loop the following steps: (1) reads from the
keyboard two numbers and an operator +, -, * or /; (2) executes the desired operation and
(3) writes the result on a new line in a file, in the format:
Operation_nb: operand1 operator operand2 = result
The exit from the loop takes place when the character x is introduced on the position of the
operator. Before finishing, write the number of executed operations in the file. The name of
the file the results are written to is given as an argument in the command line.

You might also like