A brief summary of test operators in shell programming:
[ -d name ] true if name is a directory and exists
[ -f name ] true if name is a file and exists
[ -s name ] true if name is an existing, not empty file
[ -r name ] true if name is a readable file (read access)
[ -w name ] true if name is a writeable file (write access)
[ -x name ] true if name is an executable file (execute access)
[ -z name ] true if name has zero length
[ -n name ] true if name has non zero length
[ string ] true if string is not empty
[ name1 = name2 ] true if string name1 and name2 are equal
[ name1 != name2 ] opposite of =
[-d dir1 -a -f prog] -a: "and" (logical "and") -o: " or " (logical "or")
[ ! -f name ] true, if file name does not exist
[ num1 -eq num2 ] true if number num1 and num2 are equal
[ num1 -neq num2 ] true if number num1 and num2 are not equal
[ num1 -lt num2 ] true if number num1 is less than number num2
[ num1 -gt num2 ] true if number num1 is greater than number num2
[ num1 -ge num2 ] true if number num1 is greater than or equal to num2
[ num1 -le num2 ] true if number num1 is less than or equal to num2
Following are some examples:
1. Check your system's info and print the shells available in your system:
#!/bin/sh2. Check whether the input names are executable files from your searching path:
# check your system's info and which shells are available
echo "The machine information: `uname -s` version `uname -r`"
for x in sh bsh bash csh tcsh ksh zsh; do
test -x /bin/$x && shells="$shells $x"
done
echo "The following shells are available in the system: $shells"
#!/bin/sh3. Print shell command arguments in reverse order:
# check whether the input names are executable files from your searching path
# if so, print the whole path of them
mypath=`echo $PATH | tr ':' ' ' `
for filename in $*; do
for apath in $mypath ;do
if [ -x $apath/$filename ]; then
echo $apath/$filename
fi
done
done | while read finded; do
ls -l $finded
done
#!/bin/sh4. Menu switch:
# Print all the arguments reversely
inputString=""
for i in $*
do
inputString="$i $inputString"
done
echo "The reverse arguements you typed are:"
echo $inputString
exit
#!/bin/sh5. Calculate the factorial of a number n!=n*(n-1)!
# interpret the input
echo "Enter a command (list/user/disk/quit/Quit):"
while read cmd
do
case "$cmd" in
list) ls -al ;;
user) who -l ;;
disk) df . ;;
quit|Quit) break ;;
*) echo "$cmd: No such command" ;;
esac
done
echo "All done"
#!/bin/sh6. Check whether the input words are existing in a given file:
#calculate the factorial of a number n!=n*(n-1)!
if [ $# -eq 0 ]; then
echo " Usage: factor.sh number"
exit 1
elif [ $# -gt 1 ]; then
echo " Too many arguments"
exit 1
fi
COUNT=0
VALUE=1
while [ $COUNT -lt $1 ]; do
COUNT=`expr $COUNT + 1`
VALUE=`expr $VALUE \* $COUNT`
done
#display the results
echo "The factorial of $1 is $VALUE"
#!/bin/sh7. Check whether the input names are executable files from your searching path:
#check if the input are valid words in a specified dictionary
if [ $# -lt 2 ]; then
echo " Usage: check-word.sh dictionary-file word1 word2 ..."
exit 1
fi
COUNT=1
TARGET=$1
shift
for WORD in $*; do
echo -n "$COUNT : "
COUNT=`expr $COUNT + 1`
echo -n "Word $WORD "
CHECK=`eval "grep -w $WORD $TARGET | wc -l"`
if [ $CHECK -eq 0 ]; then
echo "is not found in $TARGET !"
else
echo "is found in $TARGET !"
fi
done
#!/bin/sh8. Check mail status and display mail headers for new and unread mails:
# check whether the input names are executable files from your searching path
# if so, print the whole path of them
mypath=`echo $PATH | tr ':' ' ' `
for filename in $*; do
for apath in $mypath ;do
if [ -x $apath/$filename ]; then
echo $apath/$filename
fi
done
done | while read finded; do
ls -l $finded
done
#!/bin/csh9. Change files' permission in directories and their subdirectories:
# check mail status and display mail headers for new and unread mail
set maildir="/var/mail"
if (-e $maildir/$USER.lock == 0) then
if ((-e $maildir/$USER != 0) && (-z $maildir/$USER == 0)) then
mailx -H | awk 'BEGIN { c = 0 } { if (($1 ~ /N/) || ($1 ~ /U/)) {print $0; c = 1} } \
END { if (c == 0) print "no new mail" }'
else
echo ' No mail for '$USER
endif
else
echo ' Your mailbox is locked'
endif
#!/bin/sh10. A recursive version to do the above task:
# Change the permissions of all files in directories including subtree.
# Use command "find" to print all files(directories) in a path or paths.
# Pipe each file(directory) name to input function "read".
# Then use the script of question1 to change the permission.
# Select one or more directories to change.
# Function current path if without argument.
if [ $1 = ? ] || [ ! -d $1 ]
then echo " Usage: ch-perm.sh [path1] [path2] ... "
exit
fi
# If no argument then set path to current directork
path=${*:-.}
find $path -depth -print | while read file
do
if [ -d $file ]; then
chmod 711 $file
elif [ -x $file ]; then
chmod 755 $file
else chmod 644 $file
fi
done
echo " Job was done successfully!"
exit
#!/bin/sh
# set the permissions: directories 711, excutable files 755, else 644.
# [ -n "not_empty_string"]; [ -e "exist_file" ];
# [ -f "regular_file" ]; [ -L "symbol_link" ]
dir=`pwd`
command=$0
echo "Directory: $dir Command: $command"
for file in *
do
if [ -d $file ]
then
echo "directory: $file "
chmod 711 $file
cd $file
$dir/$command
echo "now directory is : `pwd` "
cd ..
elif [ -x $file ]
then
echo "excutable file: $file "
chmod 755 $file
else
echo "regular file: $file "
chmod 644 $file
fi
done
echo " Job was done successfully!"
exit