The program must start on the following line (must be on the first line of the file) : #! / bin/sh # symbol! Used to tell the system that the parameters following it are the program used to execute the file. In this example we use /bin/sh to execute the program. When the script is finished, it must also be executable if it is to be executed. To make the script executable: compile chmod +x filename so that it can be run with./filename
2 comments In shell programming, comments are indicated by a sentence beginning with # until the end of the line.
3 Variables In shell programming, all variables are composed of strings and do not need to be declared. To assign to a variable, write: #! Echo “a is:” echo a Sometimes it is easy to confuse variable names with other characters, such as: Num =2echo “thisisthea sometimes it is easy to confuse variable names with other text, e.g. : num=2echo” thisisthea sometimes it is easy to confuse variable names with other text, e.g. : Num =2echo “thisisthenumnd” this will not print “thisisthe 2nd”, just “thisisthe” because the shell will search for the variable numnd, which has no value. We can use curly braces to tell the shell that we want to print the num variable: num=2 echo “This is the $
{num}
Nd “this will print: this is the 2nd
4 Environment variables Variables processed by the export keyword are called environment variables. We won’t discuss environment variables because they are typically used only in login scripts.
5 Shell**** Commands and flow control Three types of commands can be used in Shell scripts: 1)Unix commands: Although any Unix command can be used in Shell scripts, there are some commands that are more commonly used. These commands are usually used for file and literal manipulation.
Syntax and functions of common commands
Echo “some text” :
Print text content on the screen
ls:
File list
Wc-l filewc -w filewc -c file:
Count the number of lines in the file Count the number of words in the file Count the number of characters in the file
cp sourcefile destfile:
File copy
mv oldname newname :
Rename or move files
rm file:
Delete the file
The grep ‘pattern’ file:
Search for strings in files such as:
The grep ‘searchstring’ file. TXT
cut -b colnum file:
Specify the range of file contents to display and print them to the standard output device for example: print characters 5 through 9 on each line cut-b5-9 file. TXT
These are two completely different commands
cat file.txt:
Output file contents to standard output device (screen)
file somefile:
Get the file type
read var:
Prompts the user for input and assigns the input to the variable
sort file.txt:
Sort the lines in file.txt
uniq:
Delete rows and columns from a text file for example:
sort file.txt | uniq
expr:
Do the math
Example: add 2 and 3expr 2 “+” 3
find:
Search for files for example, search by file name
find . -name filename -print
tee:
Output data to standard output devices (screens) and files such as:
somecommand | tee outfile
basename file:
Return a file name that does not contain a path such as basename /bin/tux
tux
dirname file:
Return the file path, for example, dirname /bin/tux
/bin
head file:
Prints the first few lines of a text file
tail file :
Prints the last few lines of the text file
sed:
Sed
Is a basic find and replace program. Text can be read in from standard input (such as a command pipeline) and output to standard output (screen). This command uses regular expressions (see Resources) to search. Not to be confused with wildcards in the shell. For example: the linuxfocus replaced with linuxfocus: cat text. The file | sed ‘s/linuxfocus linuxfocus/’ > newtext. The file
awk:
Awk is used to extract fields from text files. By default, the field separator is a space, and you can specify other separators using -f.
Catfile. TXT | awk – F, ‘{print “, “1”, “1”, “3}’
Here we use “, “as the field separator and print both the first and third fields. If the file content is as follows: Adam Bor, 34, IndiaKerryMiller, 22, USA The command output is Adam Bor, IndiaKerryMiller, USA
- Concepts: pipes, redirection and backtick
These are not system commands, but they are really important.
1. The pipe
(|)
—–
Take the output of one command as the input of another. Grep “hello” file. TXT | wc – l in the file. TXT search contains a “hello” in the number of line and calculate the adults. The output of the grep command is used as the input of the WC command. Of course you can use multiple commands.
2. Redirect —–
Output the result of a command to a file instead of standard output (screen).
3. > — — — — —
Writes to the file and overwrites the old file
4. > > — — — — —
Add to the end of the file, keeping the contents of the old file.
5. Backslash —–
Use the backslash to take the output of one command as a command line argument to another. -mtime-1-type f-print Is used to find the files that have been modified in the last 24 hours (-mtime -2 indicates the last 48 hours). If you want to package all the files you find, you can use the following Linux script: #! /bin/sh # The ticks are backticks (‘) not normal quotes (‘): tar -zcvf lastmod.tar.gz ‘find. -mtime-1-type f-print’
- Process control
**1. If ** “if” expression executes the part following then if the condition is true: if… .; Then… Elif… .; Then… . The else… Fi In most cases, you can use the test command to test a condition. For example, you can compare strings, determine whether files exist and are readable…
** is usually used with “[]” to indicate conditional tests. ** Note that the space here is important. Make sure the square brackets are blank. [-f “somefile”] : somefile [-x “/bin/ls”] : somefile [-x “/bin/ls”] : somefile [-x “/bin/ls”] : somefile [-n “var” \] : var variable [“a”=” a”=”a” =”b”] : Check whether a is equal to A and A is equal to B. Run man test to view the types of all test expressions that can be compared and determined. Execute the following script directly: #! /bin/sh if [ “SHELL” = “/bin/bash” \]; Then echo “Your login shell is the bash (bourne again shell)” else echo “Your login shell is not bash but shell” fi The variable SHELL contains the name of the login SHELL, which we compared to /bin/bash. Those familiar with THE C language may appreciate the following expression: \[-f “/etc/shadow” \] && echo “This computer uses shadow passwors” You can also think of the and operations in logical operations. In the preceding example, “This computer uses shadow passwors” is printed if the /etc/shadow file exists. Also or operator (| |) is also available in the shell programming. Here’s an example: #! /bin/sh mailfolder=/var/spool/mail/james \[-r “mailfolder”] ‘{echo “Can not read mailfolder”; exit 1; } echo “mailFolder has mail from:” grep “^ from” $mailFolder The script checks whether the MailFolder is readable. Print the “From” line in the file if it is readable. If it is unreadable or the operation takes effect, the script exits after an error message is printed. There is a problem here, and that is that we must have two commands: ◆ Print an error message and ◆ exit the program we use curly braces to put the two commands together as one command in the form of an anonymous function. The general functions are mentioned below. We can do anything with an if expression without the and or operator, but it is much more convenient to use the and or operator.
2.case
Case: Expressions can be used to match a given string, not a number.
case … in
…). do something here ;;
esac
Let’s look at an example. The file command identifies the file type of a given file, for example:
file lf.gz
This returns:
lf.gz: gzip compressed data, deflated, original filename,
last modified: Mon Aug 27 23:09:18 2001, os: Unix
We took advantage of this by writing a script called SmartZip that automatically unzips bzip2, gzip, and zip types of compressed files:
#! /bin/sh
ftype=`file “$1″`
case “$ftype” in
“$1: Zip archive”*)
unzip “$1” ;;
“$1: gzip compressed”*)
gunzip “$1” ;;
“$1: bzip2 compressed”*)
bunzip2 “$1” ;;
*) echo “File $1 can not be uncompressed with smartzip”;;
esac
You may have noticed that we used a special variable $1 here. This variable contains the value of the first argument passed to the program.
That is, when we run:
smartzip articles.zip
$1 is the string articles.zip
3. selsect
Select expressions are an extension of Bash and are especially good for interactive use. The user can choose from a different set of values.
select var in … ; do
break
done
. now $var can be used ….
Here’s an example:
#! /bin/sh
echo “What is your favourite OS?”
select var in “Linux” “Gnu Hurd” “Free BSD” “Other”; do
break
done
echo “You have selected $var”
Here is the result of running the script:
What is your favourite OS?
-
Linux
-
Gnu Hurd
-
Free BSD
-
Other
#? 1
You have selected Linux
4.loop
The while-loop will run until the expression test is true. will run while the expression that we test for is true.
The keyword “break” is used to break out of the loop. The keyword “continue” is used to skip to the next loop without executing the rest of the loop.
while … ; do
.
done
The for-loop expression looks at a list of strings separated by Spaces and assigns it to a variable:
for var in …. ; do
.
done
In the following example, ABC will be printed to the screen separately:
#! /bin/sh
for var in A B C ; do
echo “var is $var”
done
Here is a more useful script, showrpm, that prints statistics for some RPM packages:
#! /bin/sh
# list a content summary of a number of RPM packages
# USAGE: showrpm rpmfile1 rpmfile2 …
# EXAMPLE: showrpm /cdrom/RedHat/RPMS/*.rpm
for rpmpackage in $*; do
if [ -r “$rpmpackage” ]; then
echo “=============== $rpmpackage ==============”
rpm -qi -p $rpmpackage
else
echo “ERROR: cannot read file $rpmpackage”
fi
done
Here comes the second special variable, $*, which contains all the input command-line argument values.
If you run the showrpm openssh.rpm w3m.rpm webgrep
In this case, $* contains three strings: openssh.rpm, w3m. RPM and webgrep.
5. The quotation marks
The program extends wildcards and variables before passing any parameters to the program. By extension, I mean that the program replaces wildcard characters (such as *) with appropriate file names and variables with variable values. To prevent programs from making this substitution, you can use quotes: Let’s take a look at an example. Suppose you have some files in the current directory, two JPG files, mail.jpg and tux.jpg.
1.2 Compiling SHELL Scripts
#ch#! /bin/sh mod +x filename
cho *.jpg union tip brew U informal cautis?./filename to execute your script. 【?? 】
This will print the result of “mail.jpg tux.jpg”.
Quotes (single and double) will prevent this wildcard extension:
#! /bin/sh
echo “*.jpg”
echo ‘*.jpg’
This will print “*.jpg” twice.
Single quotes are more strict. It prevents any variable expansion. Double quotes prevent wildcard extensions but allow variable extensions.
#! /bin/sh
echo $SHELL
echo “$SHELL”
echo ‘$SHELL’
The running results are as follows:
/bin/bash
/bin/bash
$SHELL
Finally, there is another way to prevent this extension, which is to use the escape character, the backslant:
echo *.jpg
echo $SHELL
This will print:
*.jpg
$SHELL
6. Here documents
Here documents are a good way to pass lines of text to a command. It’s useful to write a helpful paragraph for each script, so if we have that here documents, we don’t have to use the echo function to print it line by line. A “Here document” with
shift by 2
–) shift; break;; # end of options
-*) echo “error: no such option $1. -h for help”; exit 1;;
*) break;;
esac
done
echo “opt_f is $opt_f”
echo “opt_l is $opt_l”
echo “first arg is $1”
echo “2nd arg is $2”
You can run the script like this:
cmdparser -l hello -f — -somefile1 somefile2
The result returned is:
opt_f is 1
opt_l is hello
first arg is -somefile1
2nd arg is somefile2
How does this script work? The script starts by looping through all the input command line arguments, comparing the input arguments to the case expression, setting a variable and removing the argument if they match. By convention on Unix systems, the first input should be a parameter containing a minus sign.
Part 2 examples
Now let’s discuss the general steps of writing a script. Any good script should have help and input parameters. And it’s a good idea to write a pseudo-script (framework.sh) that contains the framework structure that most scripts need. At this point, when writing a new script, we just need to execute the copy command:
cp framework.sh myscript
And then you insert your own function.
Let’s look at two more examples:
Conversion from binary to decimal
Script B2D converts binary numbers (such as 1101) to corresponding decimal numbers. Here is another example of using expr to do math:
#! /bin/sh
# vim: set sw=4 ts=4 et:
help()
{
cat <
b2h — convert binary to decimal
USAGE: b2h [-h] binarynum
OPTIONS: -h help text
EXAMPLE: b2h 111010
will return 58
HELP
exit 0
}
error()
{
# print an error and exit
echo “$1”
exit 1
}
lastchar()
{
# return the last character of a string in $rval
if [ -z “$1” ]; then
# empty string
rval=””
return
fi
# wc puts some space behind the output this is why we need sed:
numofchar=`echo -n “$1” | wc -c | sed ‘s/ //g’ `
# now cut out the last char
Rval = ` echo -n “1” ∣ cut – b1 “| the cut – b 1” ∣ cut – bnumofchar `
}
chop()
{
# remove the last character in string and return it in $rval
if [ -z “$1” ]; then
# empty string
rval=””
return
fi
# wc puts some space behind the output this is why we need sed:
numofchar=`echo -n “$1” | wc -c | sed ‘s/ //g’ `
if [ “$numofchar” = “1” ]; then
# only one char in string
rval=””
return
fi
numofcharminus1=`expr $numofchar “-” 1`
# now cut all but the last char:
Rval = ` echo -n “1” ∣ cut – b0-1 | “cut” 0-1 – b ∣ cut – b0 – ` {numofcharminus1}
}
while [ -n “$1” ]; do
case $1 in
-h) help; shift 1;; # function help is called
–) shift; break;; # end of options
-*) error “error: no such option $1. -h for help”;;
*) break;;
esac
done
# The main program
sum=0
weight=1
# one arg must be given:
[ -z “$1” ] && help
binnum=”$1″
binnumorig=”$1″
while [ -n “$binnum” ]; do
lastchar “$binnum”
if [ “$rval” = “1” ]; then
sum=`expr ” weight””+””weight” “+” “weight””+””sum”`
fi
# remove the last position in $binnum
chop “$binnum”
binnum=”$rval”
weight=`expr “$weight” “*” 2`
done
echo “binary
sum”
The script uses an algorithm that utilizes both decimal and binary weights (1,2,4,8,16,..) For example, binary “10” can be converted to decimal like this:
0 times 1 plus 1 times 2 is 2
To get a single binary number we use lastchar. This function counts the number of characters using WC -c, and then fetches the last character using the cut command. The Chop function removes the last character.
File circulator
Maybe you’re one of those people who wanted to save all of their outgoing mail in one file, but after a few months
Later, the file may become so large that it slows access to the file. The following script is rotatefile
Can solve this problem. This script can rename the mail save file (let’s say outmail) to outmail.1,
For outmail.1 it becomes outmail.2 and so on…
#! /bin/sh
# vim: set sw=4 ts=4 et:
Ver = “0.1”
help()
{
cat <
rotatefile — rotate the file name
USAGE: rotatefile [-h] filename
OPTIONS: -h help text
EXAMPLE: rotatefile out
This will e.g rename out.2 to out.3, out.1 to out.2, out to out.1
and create an empty out-file
The max number is 10
version $ver
HELP
exit 0
}
error()
{
echo “$1”
exit 1
}
while [ -n “$1” ]; do
case $1 in
-h) help; shift 1;;
–) break;;
-*) echo “error: no such option $1. -h for help”; exit 1;;
*) break;;
esac
done
# input check:
if [ -z “$1” ] ; then
error “ERROR: you must specify a file, use -h for help”
fi
filen=”$1″
# rename any .1 , .2 etc file:
for n in 9 8 7 6 5 4 3 2 1; do
if [ -f ” filen.filen.filen.n” ]; then
p=`expr $n + 1`
echo “mv filen.filen.filen.n filen.filen.filen.p”
mv filen.filen.filen.n filen.filen.filen.p
fi
done
# rename the original file:
if [ -f “$filen” ]; then
echo “mv filenfilen filenfilen.1”
mv filenfilen filenfilen.1
fi
echo touch $filen
touch $filen
How does this script work? After detecting that the user has provided a filename, we do a 9 through 1 loop. File 9 is named 10, file 8 is renamed 9, and so on. After the loop is complete, we name the original file file 1 and create an empty file with the same name as the original file.
debugging
The simplest debugging command is, of course, to use the echo command. You can use echo to print any variable value anywhere you suspect something has gone wrong. This is why most shell programmers spend 80% of their time debugging. The nice thing about Shell programs is that they don’t need to be recompiled, and it doesn’t take much time to insert an echo command.
The shell also has a real debug mode. If there is an error in the script” Strangescript “, you can debug it like this:
sh -x strangescript
This will execute the script and display the values of all variables.
The shell also has a mode where you don’t need to execute a script, just check the syntax. It can be used like this:
sh -n your_script
This will return all syntax errors.