I. Shells
Definition of Shell : - Program layer providing a human interface point and user environment for communication with the Linux kernel |
Different shells exist in Linux :
autoload -U compinit compinit
II. bash (Bourne Again Shell)
a. Features of bash
There are also useful tests for shell programming:
b. Shell Initialization and De-Initialization
As an example, insert the line cat face.txt (where face.txt contains an illustrated face) into ~/.bash_history
c. Shell Environment Variables
Character | Meaning |
\! | Displays the history number of this command. |
\# | Displays the command number of the current command. |
\$ | Displays a $ in the prompt unless the user is root. When the user is root, it displays a #. |
\\ | Displays a backslash. |
\d | Displays the current date. |
\h | Displays the host name of the computer on which the shell is running. |
\n | Prints a newline character. This will cause the prompt to span more than one line. |
\nnn | Displays the character that corresponds to the octal value of the number nnn. |
\s | The name of the shell that is running. |
\t | Displays the current time. |
\u | Displays the username of the current user. |
\W | Displays the base name of the current working directory. |
\w | Displays the current working directory. |
color | code | color | code |
black | 0;30 | dk.gray | 1;30 |
red | 0;31 | lt.red | 1;31 |
green | 0;32 | lt.green | 1;32 |
brown | 0;33 | yello | 1;33 |
blue | 0;34 | lt.blue | 1;34 |
purple | 0;35 | lt.purple | 1;35 |
cyan | 0;36 | lt.cyan | 1;36 |
l.gray | 0;37 | white | 1;37 |
d. Shell Meta-Characters
The following are shell meta-characters, also known as wildcards:In order to prevent the > operator from overwriting the file, use $noclobber=1 (or anything) ($set noclobber for tcsh), or simply use >> .
x. CygWin
III. zsh Install using cygwin under windows.
x. zshrc
# Cygwin .zshrc by Samar Abbas 12/09/2003 # Autocompletion Init Section autoload -U compinit compinit # Spell Checking Section setopt correct # correct spelling of commands setopt correct_all # correct spelling of all args # Auto Change Directory Section setopt autocd autopushd setopt pushdignoredups # Prompt Section # RPS1 (Right hand side Prompt Symbol): set to data and time autoload -U promptinit promptinit prompt adam1 blue green green RPS1=$'%{\e[1;31m%} {%D} %{\e[1;45m%} %{\e[2;33m%} <%*> %{\e[0m%}' # Auto list and menu selection Section setopt auto_list # auto list choices in ambiguous selectn aftersetopt auto_menu # cycle menu options using setopt menu_complete # insert first matching entry in list setopt NO_bash_auto_list # overrides auto_list and forces 3x press setopt glob setopt glob_complete # filename generation setopt list_ambiguous setopt NO_clobber # don't overwrite existing files # export DISPLAY to remotemachine (works in telnet only) export DISPLAY=$REMOTEHOST:0.0 # History options HISTSIZE=2000 HISTFILE="$HOME/.zsh_history" SAVEHIST=2000 setopt append_history setopt inc_append_history setopt share_history setopt extended_history # beginning time:elapsed seconds:command added to history file setopt hist_expire_dups_first # Logout Options setopt check_jobs # report job status before exit, twice exit ends TMOUT=1800 # Custom Autocomplete List: host names hosts=(alpha beta gamma cyberspace.org) compctl -k hosts ssh scp ping host telnet # Watch Section: Watch for Friend and Foe WATCHFMT='%n %a %M %T' LOGCHECK=3 export LOGCHECK watch=all # Alias Section alias "textpad=C:/Program\\ Files/TextPad\\ 4/TextPad.exe"
%T (date 24h) %t = %@ (precise 12h time) %D (date in yy-mm-dd) %* (precise 24h time) %w (date day-dd) %W (date m/dd/yy) %l (current tty) %h = %! (history no.) %n (username) %U | %u (start/stop underline mode) %S | %s (start/stop standout mode) %B | %b (start/stop boldface mode) %M (full server name) %m (hostname upto first .) %~ (pwd, with home dir = ~) %/ (pwd)
VI. Shell Programming
a. Basic Shell Scripts
|
echo "Hello World" echo "From Samarstan" echo '\007\c' # sysv bell; echo -n '^G' : bsd bell |
|
#! /bin/bash # magic nos: 1st 16 bits, tell kernel this is not bin exec who echo '******************' ls echo "******************" # This is a comment ps echo '******************' |
It is often customary to write the shell at the top of the script, as in #! /bin/bash , and # lines are comments.
b. Quotation Marks
The double quotation marks (""), the single quotation marks ('') or grave accents, and the backslash (\) are all used to hide special characters from the shell.
|
echo '******************' echo "hello $LOGNAME" echo "******************" |
Note that using echo 'hello $LOGNAME' would not work, returning "hello there $LOGNAME" as the single quotes would hide the variable from the shell.
c. Variables
Variable | Use |
$# | no. of cmd-line args. |
$- | options suppld to shell |
$? | exit value of the last cmd. |
$$ | process no. of currt proc. |
$! | process no. of last cmd done in bg |
$i | arg on cmd line i=1-9 |
$0 | first word of the entered cmd (ie. name of shell program). |
$* | all args on the cmd line ("$1 $2 ... $9"). |
$@ | all args on the cmd line, individually quoted ("$1" "$2" ...). |
|
echo $1 $2 $3 were the individual arguments echo $0 is the name of the shell script echo "there were $# arguments." echo $* 'were all the arguments' echo '$@:' $@ |
|
#! /bin/bash echo "Please enter a word, sentence or number" read x echo "You entered :" $x |
|
#! /bin/bash dir=`pwd` when=`date` echo 'You are using the' $dir 'directory on' $when |
|
#! /bin/bash set `date` echo $* echo $2 $3, $6 |
The first command uses sets the command-line argument variables to the output of the date command.
d. Conditional Statements
if [ expression ] then commands elif [ expression2 ] then commands else commands fielif statement is an abbreviation of else if. This statement is executed only if none of the expressions associated with the if statement or any elif statements before it were true. The commands associated with the else statement are executed only if none of the expressions associated with the if statement or any of the elif statements were true.
|
if [ -f .profile ] then echo "There is a .profile file in this directory." else echo "Could'nt find a .profile file in this directory." fi |
|
#! /bin/bash if (test $# = 0) then echo 'Please supply at least 1 argument' exit fi echo 'Program is running' |
until expression do commands done
|
secretname='samar' name='noname' echo 'Try to guess the secret name!' echo until (test "$name" = "$secretname") do echo 'Your guess: ' $name read name done echo 'You did it!' |
case test-string in pattern-1 ) commands-1 ;; pattern-2 ) commands-2 ;; pattern-3 ) commands-3 ;; . . . *) commands ;; esac
|
echo 'Enter A, B, or C:' read letter case $letter in A) echo 'You entered A' ;; B) echo 'You entered B' ;; C) echo 'You entered C' ;; *) echo 'You did not enter A, B, or C' ;; esac |
for.sh#!/bin/sh for i in 1 2 3 4 5 do echo "Looping ... number $i" done mkdir rc{0,1,2,3,4,5,6,S}.d
while.sh#!/bin/sh INPUT_STRING=hello while [ "$INPUT_STRING" != "bye" ] do echo "Please type something in (bye to quit)" read INPUT_STRING echo "You typed: $INPUT_STRING" done
bash_expect.sh:set password [index $argv 2] spawn passwd [index $argv 1} expect "*password:" send "$password\r" expect "*password:" send "$password\r" expect eof
bash_rename.shfor f in *.html; do base=`basename $f .html` # remove the suffix and its dot .html mv $f js_${base}.html # add new prefix js_ and suffix done
bash_while_lang.sh#!/bin/sh while read f do case $f in hello) echo English ;; howdy) echo American ;; gday) echo Australian ;; bonjour) echo French ;; "guten tag") echo German ;; *) echo Unknown Language: $f ;; esac done < myfile
multiple_wget.sh#!/bin/sh for i in 1 2 3 4 5; do echo "Trying to execute wget -b http://www.yahoo${i}.com"; wget -b http://www.yahoo${i}.com; done;
wget_cmdline.sh#!/bin/bash for i in $( cat f.txt ); do echo item: $i done
cyclical_wget_hobsonjobson.sh#! /bin/bash (( maxC = 181 )) (( i = 0 )) while (( i < maxC )) do echo "trying to get http://dsal.uchicago.edu/cgi-bin/ddsa/getobject_?.p.0:"$i"./projects/artfl0/databases/dicos/philologic/hobson/IMAGE/" wget "http://dsal.uchicago.edu/cgi-bin/ddsa/getobject_?.p.0:"$i"./projects/artfl0/databases/dicos/philologic/hobson/IMAGE/" (( i += 1 )) done echo completed
factorial.sh#!/bin/sh factorial() { if [ "$1" -gt "1" ]; then i=`expr $1 - 1` j=`factorial $i` k=`expr $1 \* $j` echo $k else echo 1 fi } while : do echo "Enter a number:" read x factorial $x done
Various script headers:#!/bin/sh #!/bin/bash #!/usr/bin/perl #!/usr/bin/tcl #!/bin/sed -f #!/usr/awk -f
test.sh#!/bin/sh if [ "$X" -lt "0" ] then echo "X is less than zero" fi if [ "$X" -gt "0" ]; then echo "X is more than zero" fi [ "$X" -le "0" ] && echo "X is less than or equal to zero" [ "$X" -ge "0" ] && echo "X is more than or equal to zero" [ "$X" = "0" ] && echo "X is the string or number \"0\"" [ "$X" = "hello" ] && echo "X matches the string \"hello\"" [ "$X" != "hello" ] && echo "X is not the string \"hello\"" [ -n "$X" ] && echo "X is of nonzero length" [ -f "$X" ] && echo "X is the path of a real file" || echo "No such file: $X" [ -x "$X" ] && echo "X is the path of an executable file" [ "$X" -nt "/etc/passwd" ] && echo "X is a file which is newer than /etc/passwd"
bash_mkfifo.sh#!/bin/bash # ==> Script by James R. Van Zandt, and used here with his permission. # ==> Comments added by author of this document. HERE=`uname -n` # ==> hostname THERE=bilbo echo "starting remote backup to $THERE at `date +%r`" # ==> `date +%r` returns time in 12-hour format, i.e. "08:08:34 PM". # make sure /pipe really is a pipe and not a plain file rm -rf /pipe mkfifo /pipe # ==> Create a "named pipe", named "/pipe". # ==> 'su xyz' runs commands as user "xyz". # ==> 'ssh' invokes secure shell (remote login client). su xyz -c "ssh $THERE \"cat >/home/xyz/backup/${HERE}-daily.tar.gz\" < /pipe"& cd / tar -czf - bin boot dev etc home info lib man root sbin share usr var >/pipe # ==> Uses named pipe, /pipe, to communicate between processes: # ==> 'tar/gzip' writes to /pipe and 'ssh' reads from /pipe. # ==> The end result is this backs up the main directories, from / on down. # ==> What are the advantages of a "named pipe" in this situation, # ==> as opposed to an "anonymous pipe", with |? # ==> Will an anonymous pipe even work here? exit 0
xlib.lib# xlib.lib # Note no #!/bin/sh as this should not spawn an extra shell. # It's not the end of the world to have one, but clearer not to. # STD_MSG="About to rename some files..." rename() { # expects to be called as: rename .txt .bak FROM=$1 TO=$2 for i in *$FROM do j=`basename $i $FROM` mv $i ${j}$TO done }
f_xlib.sh#!/bin/sh # function2.sh . ./xlib.lib echo $STD_MSG rename txt bak
Exit codes: a no. 0-255 returned by any Unix command when it returns control to parent process. success = exit 0; failure = non-zero exit code.
exit.sh#!/bin/sh # Second attempt at checking return codes grep "^${1}:" /etc/passwd > /dev/null 2>&1 if [ "$?" -ne "0" ]; then echo "Sorry, cannot find user ${1} in /etc/passwd" exit 1 fi USERNAME=`grep "^${1}:" /etc/passwd|cut -d":" -f1` NAME=`grep "^${1}:" /etc/passwd|cut -d":" -f5` HOMEDIR=`grep "^${1}:" /etc/passwd|cut -d":" -f6` echo "USERNAME: $USERNAME" echo "NAME: $NAME" echo "HOMEDIR: $HOMEDIR"
telnet.sh: $ ./telnet.sh | telnet#!/bin/sh host=127.0.0.1 port=23 login=steve passwd=hellothere cmd="ls /tmp" echo open ${host} ${port} sleep 1 echo ${login} sleep 1 echo ${passwd} sleep 1 echo ${cmd} sleep 1 echo exit
append.shfor x in `ls`; do # foreach file (`ls -1`) # {echo "some text" ; cat f} > g; mv g f (cat header.txt; cat $x) > g; mv g $x cat footer.txt >> $x done # echo -e "12345\n$(cat tt)" > tt # sed '1i\\ # hello world' tt >tt.out # delete lines by no or match usg sed
IV. Converting DOS Batch Files to Shell Scripts
Batch File Operator | Shell Script Equivalent | Meaning |
---|---|---|
% | $ | command-line parameter prefix |
/ | - | command option flag |
\ | / | directory path separator |
== | = | (equal-to) string comparison test |
!==! | != | (not equal-to) string comparison test |
| | | | pipe |
@ | set +v | do not echo current command |
* | * | filename "wild card" |
> | > | file redirection (overwrite) |
>> | >> | file redirection (append) |
< | < | redirect stdin |
%VAR% | $VAR | environmental variable |
REM | # | comment |
NOT | ! | negate following test |
NUL | /dev/null | "black hole" for burying command output |
ECHO | echo | echo (many more option in Bash) |
ECHO. | echo | echo blank line |
ECHO OFF | set +v | do not echo command(s) following |
FOR %%VAR IN (LIST) DO | for var in [list]; do | "for" loop |
:LABEL | none (unnecessary) | label |
GOTO | none (use a function) | jump to another location in the script |
PAUSE | sleep | pause or wait an interval |
CHOICE | case or select | menu choice |
IF | if | if-test |
IF EXIST FILENAME | if [ -e filename ] | test if file exists |
IF !%N==! | if [ -z "$N" ] | if replaceable parameter "N" not present |
CALL | source or . (dot operator) | "include" another script |
COMMAND /C | source or . (dot operator) | "include" another script (same as CALL) |
SET | export | set an environmental variable |
SHIFT | shift | left shift command-line argument list |
SGN | -lt or -gt | sign (of integer) |
ERRORLEVEL | $? | exit status |
CON | stdin | "console" (stdin) |
PRN | /dev/lp0 | (generic) printer device |
LPT1 | /dev/lp0 | first printer device |
COM1 | /dev/ttyS0 | first serial port |