Вы находитесь на странице: 1из 7

UNIX/LINUX script examples, rules

http://www.cs.iastate.edu/~cs104/notes/scripts.html

Intro

Input

Variables

Interpreting variables

ifs

Loops

Misc

Index of commands

Scripting rules
Scripts: commands in files A program or command is executed by typing the name, with any inputs after it. A file with commands in it may be executed the same way, if it has execute permission (chmod u+x file or chmod 700 file.) These are called scripts. Lines in the file are run as if they were typed at the keyboard. There are a few extra commands that are only useful in scripts:
script sample runs

% cat abc ls # First line: head -n1 abc echo done boss

% abc aardvark.dat abc stuff.txt ls done boss

The echo UNIX command prints all of it's inputs to the screen, with a space between them. A # at the start of any line is a comment -- the line is ignored (but #! on the first line is special.) As usual with inputs, extra spaces are ignored. ""'s can save spaces (they really turn it all into one space-containing input):
script sample run

echo a echo "a

b b

c c"

% abc a b c a b

The second echo has two inputs: "a b c" and d. c d

To keep echo on the same line, use the -n option:


script sample run

% cat abc echo -n echo test echo is here echo again

% abc echo test is here again

Input/Parameters Inputs are "numbered" $1, $2, $3, ... . $0 is the command name. $# is the number of parameters, and is made automatically when you run a script. Parameters not entered can be used, and are "" (no letters.)
script sample runs

echo "Running:" $0 echo $2 $4 $6 $8 echo "Total inputs: " $#

% xyz a b c d e f g h i j k l Running: xyz b d f h Total inputs: 12 % xyz baby doggy Running: xyz

1 of 7

4/9/2014 6:18 AM

UNIX/LINUX script examples, rules

http://www.cs.iastate.edu/~cs104/notes/scripts.html

doggy Total inputs: 2

$@ is a short-cut for $1 $2 $3 ... . It is all of the inputs, with spaces between them. It is mostly useful to have a for loop (later) look at all inputs. The shift command moves all input parameters (not $0) "left." It removes $1, moves $2 to $1, and so on. It can also be useful in loops:
script sample runs

echo All: $@ shift echo "New first:" $1 shift echo "New first:" $1 echo "All:" $@

%xyz a b c All: a b c New first: New first: All: c d e

d e f d e f b c f

Variables You can make your own variables just by picking a name. Give it a value with = (there cannot be any spaces on either side of the =.) To look up the value, put a $ in front of the name:
script sample runs

a=grumpy b="sleepy sneezy" echo a X b echo $a X $b ls=dopey echo ls X $ls ls $ls a=X$1${a}Y echo "-->" $a

%xyz happy a X b grumpy X sleepy sneezy ls X dopey xyz stuff.txt scripts.html dopey: command not found --> XhappygrumpyY

This is different from many computer languages, when it is obvious you are using a variable (examples: =, for a in, read a) leave out the $. When you want to look in a variable, use the $. It is the only way the script can tell the letter a from the contents of box a. In the line a=X$1${a}Y, the {}'s are to let bash know you want the variable a. Without it, it would look up (the nonexistant) $aY. {}'s are optional when they are not needed (${1} is the same as $1.) Interpreting variables and commands Variables, like $abc or $1, are substituted before most other things happen. This can make new words, that are checked in the normal way. You can do some strange tricks with this, such as putting two things together to make a command, or a pathname:
script sample runs

% cat abc $1$2 $1 $2/stuff.txt

% abc l s aardvark.dat abc stuff.txt l: command not found

2 of 7

4/9/2014 6:18 AM

UNIX/LINUX script examples, rules

http://www.cs.iastate.edu/~cs104/notes/scripts.html

%abc cat xxx catxxx: no such command cat: xxx/stuff.txt: file not found

Most special characters (like *) can be put in double-quotes to treat them as letters. But, variables or parameters (or anything with a $) are still looked up. To treat $ as a normal character, use single quotes (' next to ENTER, not the upper-right -- that is a back-quote):
script sample runs

echo "abc$1de$2f" a=lazy echo "a$a" 'a$a' echo $a"te"

% abc tiger puma abctigerdepumaf alazy a$a lazyte

Besides "start of line=run this command", the script can't tell the difference between the letter 5, the number 5 (seems silly, but the letter 5 plus the letter 0 is 50; sometimes we want that,) the command 5 (you can name a script 5) or the 5th input ($5), unless you tell it. You can force something not at the start of a line to be a command with $(word). This is completely different from the $ to look up a variable. It can be useful for assigning variables, and, later, is useful in loops:
script sample runs

a=$( echo $1 | cut -c1-2) echo First two letters are $a ls=xyz echo ls echo $ls echo $(ls) xyz=ls echo $($xyz)

% abc panther First two letters are pa ls xyz aardvark.dat abc stuff.txt aardvark.dat abc stuff.txt

To do math, use $((math)). Again, this use of $ has nothing to do with variables at all:
script sample runs

abc=10 echo 1+4 $1+4 $1+$abc echo $((1+4)) $(($1+4)) $(($1+$abc)) echo $((1+1))+$((2+2)) echo $(1+1)

% abc 6 1+4 6+4 6+10 5 10 16 2+4 1+1 : command not found

Ifs and tests It is possible to check parameters and variables to see if they are a certain word; or are less than, greater than, ... ; or check if they are filenames, directories, ... . This is done using an if with the test command (%info test for all of the rules):
script sample runs

if test $1 -lt 10 then echo $1 is less than 10 fi if test -f $1

% abc 6 6 is less than 10 6 isnt a file! % abc stuff.txt

then and fi are required. The else is

3 of 7

4/9/2014 6:18 AM

UNIX/LINUX script examples, rules

http://www.cs.iastate.edu/~cs104/notes/scripts.html

then echo $1 is in this dir else echo $1 isnt a file! fi

line 3: not a math expression stuff.txt is in this dir

optional. Indentation is just to make it look nice. Errors (if test stuff.txt

-lt 10) will produce a message, but the script keeps running. Brackets are a shorthand for the test command (but they need spaces around them.) if test $1 -eq 2 is the same thing as if [ $1 -eq 2 ]. Many people prefer to combine the if and then (using a semicolon.) Oddly, then may not have a semi colon after it: if test $1 -le 10; then echo "input is 10 or less"; fi. An if may be nested inside another if, following the same rules. This checks whether both inputs are files:
script sample runs

# swap two files (if they exist): if test -f $1 then if test -f $2 then mv $1 tempfile.temp mv $2 $1 mv tempfile.temp $2 else echo "$2 is not a file. Quitting" fi else echo "$1 isn't a file" fi

%swap xhgj abc.dat xhgj is not a file. Quitting %swap abc.dat hkjs hkjs isn't a file %swap abc.dat def.dat

The middle if is indented, with its else and fi lined up, to hopefully make it a little easier to read. An alternate would be to combine into one big if with nots and ors (these can get tricky) to say "if $1 or $2 isn't a file": if [ ! -f $1 -o ! -f $2 ]. An if does not need a test command after it. The if really just runs the next command and checks the "exit status." An exit status of 0 means true. For examples, test 5 -gt 8 has an exit status of 1 (which means false,) test -d "WWW" might have an exit status of 0 (there is a WWW dir,) cat a.dat has exit status 0 and ls notafile has exit status 1. The man pages describe the exit status's. In general, "normal" unix commands use: 0=no errors, not-0=type of error. Even after an if, they will also produce output (which you should redirect to /dev/null.) For example, if cat abc.dat &> dev/null is a (bad) way to check if abc.dat exists (recall &> is a short cut for > and 2> combined.) test was specially written to produce a useful exit status for use with if. But, for example, grep fox a.dat prints lines with the word "fox" and returns 0 if there were any. This is a way to say "if file $1 has the word 'fox' in it": if grep fox "$1" > /dev/null Loops The most useful type of loop looks like:

4 of 7

4/9/2014 6:18 AM

UNIX/LINUX script examples, rules

http://www.cs.iastate.edu/~cs104/notes/scripts.html

It expects a list, separated by spaces, after the for a in. a is a variable (probably one you haven't used before.) It assigns each item in the list to a and performs the lines between do and done for each. In this case, a will be LIST, then OF, then STUFF, and the output will be XLISTX XOFX XSTUFFX. for a in LIST OF STUFF do # thing to do goes here echo -n "X${a}X" done This is useful when you use a command to generate the list: for a in $@ Every input for a in $(cat a.txt) Every word in a.txt for a in $(cat a.txt | tr " " "#") Really bad way to get every line in a.txt for a in $(ls) Everything in current directory for a in $(find . -name " ") Everything in current dir, recursively (find gives complete path names.) Every line in a.txt (until a blank line). It is tricky: cat a.txt | ( Things in ()'s count as one command. cat a.txt pipes a.txt to the read a while test -n $a loop. read a reads lines from the keyboard, which is a.txt because of do the pipe. test -n checks a is not nothing (a blank line.) #use $a here A better way to do it is test $? -neq 0. $? is true if the last read a command "worked." read a "works" if there was a line left in the done ) file. This is very similar to a loop in a "real" programming language. count=0 while test $count -lt 10 do #do something for 0,1,2...9 count=$(($count+1)) done Counting to 10:

Misc problems text file busy: Using cat > abc to write to abc works fine, but legally ends with ^D (the end-of-file character.) Typing ^Z suspends the command. This means it is still running, just not going anywhere. It can be restarted later. If you try to run abc the computer may think you are still writing to it (technically, you are) and tell you the text file is busy right now. bash: abc not found: When a bash script is run, it first runs .bashrc. Our system guys added a line at the end of .bashrc, cd ~/, that fixes some problem somewhere else and makes bash not really work. They assumed everyone uses the older sh instead of bash. What happens is you type % abc, the computer sees is a script (not a compiled program) and starts a new bash program to run it. It runs .bashrc, goes home, and then can't find abc. Comment out that line to fix this problem. For fun, add a line echo "Running, boss" to see it really does run .bashrc.

5 of 7

4/9/2014 6:18 AM

UNIX/LINUX script examples, rules

http://www.cs.iastate.edu/~cs104/notes/scripts.html

Typing % sh abc runs it under the old sh shell. Typing %bash abc runs it under bash. Typing just % abc runs it under your current shell (which is probably bash (%finger username to check.) A "real" shell always starts with a line like: #! /bin/sh which tells it which shell to use for running the script (yes, # is a comment, but #! as the first thing is special.) cd in a script: In technical-speak, a script forks off a new process that gets a copy of the current state. That means it is like opening a new window that starts in the same directory as when you ran it. As usual, if you give a long path to run a script from a different directory, it still starts in the current dir. A script can use cd in the normal way, and will change the directory for the script, but as soon as the script ends, the imaginary window closes and you are back where you started, in the same dir. Index of commands $1, $2, ... First input, second input, ... $0 Name of script (command you typed to run it.) $# Number of inputs $@ All inputs (1-end) with a space between $? Return value of last command (tricky to use.) shift move all inputs one smaller ($1=$2,) reduces $# by one. # Comment. Must be first thing in line $abc Look up value of abc variable $(abc) Run command "abc". $($abc) looks up abc and runs it. $((3+4)) Do math. Without this, 3+4 is three-letter word "3+4" ${abc} {}'s are optional parenthesis. They are needed for parms past 9 (${10}). ${1:3} Substring of $1, starting at 3rd position. ${abc:2:4} Substring of abc, starting at 2nd position and using next 4 characters. [ ] Short cut for test if test -f stuff.dat then fi fi if test happy -eq $1 then else General format for if

for a in this that other do done

while test $1 -le 5 do done

General format for for and while

read a Read one line from keyboard and put in variable a 'abc' (quotes near ENTER): Treat this as a bunch of letters. "abc" (double quotes): Expend all $-rules, but otherwise treat as a bunch of letters. `abc` (back-tic [upper-left]): same as $(abc). Runs command. eval abc: Evaluate. Also same as $(abc).

6 of 7

4/9/2014 6:18 AM

UNIX/LINUX script examples, rules

http://www.cs.iastate.edu/~cs104/notes/scripts.html

script

sample run

for a in 4 8 3 7 13 4 do echo -n $a" " if test $a -ge 5 then echo "big" else echo "small" fi done

%forexample 4 small 8 big 3 small 7 big 13 big 4 small

The lines between do and done are run six times, with a equal to each number. -ge means >=. Indentation is just to make it easier to read.

script

sample run

if [ $# -ne 1 -o ! -f $1 ] then echo "Usage: $0 FILENAME" exit 1 fi words=0 for a in $(cat $1) do # echo "["$a"]" words=$((1+$words)) done echo "Num of words is" $words %wordcount abc.dat Num of words is 32

$(cat $1) simply "pastes" that file after for a in, which then looks at every word. Note the output of cat is automatically redirected (it does not go to the screen.) words is a standard counter, with one added for each word, in the awkward script manner. If you have a lot of math, use a more formal programming language.

The first part is a standard check: if there is not one input, or it is not a file (-o (letter O) is or, ! is not -- see %info test)

7 of 7

4/9/2014 6:18 AM

Вам также может понравиться