Short: New shell commands (IF, FOR) +source Author: Aaron "Optimizer" Digulla (digulla@fh-konstanz.de) Uploader: Aaron "Optimizer" Digulla (digulla fh-konstanz de) Type: util/sys Architecture: m68k-amigaos This directory contains a couple of commands which replace existing CLI commands or introduce new ones. The commands have been written with the goal of maximum compatibility in mind. All commands accept Amiga and UNIX-bourne-shell compatible argument lists. Full source is included. If you unpack the archive, specify "-a" as option to preserve the pure bits or set them later. All commands are pure and can be made resident (some even have to be). FOR --- FOR var IN [list] [;] DO [;] [cmdlist] [;] DONE Note that you must enclose ; in "" as in: FOR test IN a b c ";" DO echo $test ";" DONE All ";" are optional except inbetween commands in the cmdlist: FOR dir IN c devs l DO cd SYS:$dir ";" dir ";" cd / DONE Also note that a CD changes the current dir and if you want to execute a series of commands in a sub-dir, you must go up again OR put the commands in a "sub shell": FOR dir IN c devs l DO ( cd SYS:$dir ";" dir ) DONE does the same as the previous version. Also note that the variables you use are not unset after the loop. thus: FOR test IN a b c ";" DO echo $test ";" DONE FOR test IN a b c ";" DO echo $test ";" DONE yields: "a b c c c c". This is due to the fact that $test is unknown when the first loop is evaluated, but when the shell reads the next line, $test is equivalent to "c" and therefore, FOR is called with "... DO echo c ; DONE" as arguments. To prevent this, you must unset the variable after (or before use): unset test FOR test IN a b c ";" DO echo $test ";" DONE unset test FOR test IN a b c ";" DO echo $test ";" DONE It is safe to use unset on a non-existing variable. IF -- IF accepts the normal arguments as the standard Amiga IF and these: IF [ testlist ] [; THEN] IF cmd [; THEN] Note that testlist has to be enclosed in [] (and they must be separated by at least a single space from all other arguments) while cmd just follows IF. If you want to put the THEN in the same line as the if, you must put ";" before it (WITH the "" !!!). Since the cmd-type is more simple, I describe it first: The command "cmd" is executed and if no error occurred, this is taken as success (ie. the condition holds) and therefore the IF body is executed. If the command fails, the ELSE part (if there is one) is executed instead. The testlist-type is a short cut for the cmd-type. You can think of IF [ testlist ] beeing a simple form of IF TEST testlist TEST is a program which reads it's arguments, interprets them and returns SUCCESS or ERROR if the arguments are "true". Example: IF [ aaa = bbb ] is the same as IF TEST aaa = bbb and is false, since "aaa" is _not_ "bbb". The = is case sensitive, while the Amiga version (IF aaa EQ bbb) is not: IF aaa EQ AAA -> TRUE IF [ aaa = AAA ] -> FALSE Test has been built into IF to speed things up a little. It takes the following options: Examine files: -G FILE FILE exists and is owned by the effective group ID -L FILE FILE exists and is a symbolic link -O FILE FILE exists and is owned by the effective user ID -S FILE FILE exists and is a socket -b FILE FILE exists and is block special -c FILE FILE exists and is character special -d FILE FILE exists and is a directory -e FILE FILE exists -f FILE FILE exists and is a regular file -g FILE FILE exists and is set-group-ID -k FILE FILE exists and has its sticky bit set -p FILE FILE exists and is a named pipe -r FILE FILE exists and is readable -s FILE FILE exists and has a size greater than zero -t standard output is opened on a terminal -t FD file descriptor FD is opened on a terminal -u FILE FILE exists and its set-user-ID bit is set -w FILE FILE exists and is writable -x FILE FILE exists and is executable FILE1 -ef FILE2 FILE1 and FILE2 have the same device and inode numbers FILE1 -nt FILE2 FILE1 is newer (modification date) than FILE2 FILE1 -ot FILE2 FILE1 is older than FILE2 Examine strings: STRING the length of STRING is non-zero (same as below) -n STRING the length of STRING is non-zero -z STRING the length of STRING is zero STRING1 = STRING2 the strings are equal STRING1 != STRING2 the strings are not equal Examine numbers: INTEGER1 -eq INTEGER2 INTEGER1 is equal to INTEGER2 INTEGER1 -ge INTEGER2 INTEGER1 is greater than or equal to INTEGER2 INTEGER1 -gt INTEGER2 INTEGER1 is greater than INTEGER2 INTEGER1 -le INTEGER2 INTEGER1 is less than or equal to INTEGER2 INTEGER1 -lt INTEGER2 INTEGER1 is less than INTEGER2 INTEGER1 -ne INTEGER2 INTEGER1 is not equal to INTEGER2 Misc: ( EXPRESSION ) EXPRESSION is true ! EXPRESSION EXPRESSION is false EXPRESSION1 -a EXPRESSION2 both EXPRESSION1 and EXPRESSION2 are true EXPRESSION1 -o EXPRESSION2 either EXPRESSION1 or EXPRESSION2 is true There are several special files that are part of IF: ELSE This replaces the Amiga ELSE command ELIF, ELSEIF These are mere copies of IF (you can use links if you want) to keep the shell happy. FI This is a synonym for ENDIF THEN A nop With these extra files, you can use real sh syntax: IF [ -f xxxx ] THEN echo xxxx exists ELSE echo xxxx doesn't exist FI To install the new version, it's not sufficient to copy the files somewhere in your path, you must also overwrite the resident version (you can undo that easily if you run into problems). All commands can be made resident but the absolute minimum is this: Resident IF Add Resident ELSE Add You can remove them later with Resident IF Remove Resident ELSE Remove to get the standard commands back again. It's a good idea to make all the other commands (ELSEIF, ELIF, THEN, etc.) resident, too, to gain speed.