[plug] script error
Craig Ringer
craig at postnewspapers.com.au
Thu Jan 12 16:14:34 WST 2006
Mr E_T wrote:
> On another note - just because two files are the same size doesn't make them the same.
> do a diff -q files
>
> if diff -q $FileA $FileB
> then
> echo same
> else
> echo different
> fi
If all you want is "do they differ" then `cmp' may be better - it's much
"dumber" than diff, and probably rather faster. It's also POSIX, so it
should be available on any system you can find.
if cmp -s "$FileA" "$FileB"; then
...
fi
Note the quotes around the file paths. This is important. If the user
specifies a file path like "my file" your script would break. You must
consider spaces in file names at EVERY variable expansion; this is one
of the more frustrating aspects of shell programming.
Jon Miller wrote:
> Any idea how to append 1 file to another? using cat file1 >> file2
> does not work in a script.
It should; the command above will append the file named "file1" to the
file named "file2", both being in the current working directory.
Did you make sure that you're referring to the right files? Did you
check for spaces in expanded arguments? Did you check that you have
permission to perform the operation? Did you actually mean "$file1" not
file1 ?
I strongly recommend that you put:
set -e -u
at the top of your script (if you're using bash). This will cause your
script to abort immediately on an error, thus forcing you to explicitly
handle "expected" failures, and making it much easier to track down
unexpected ones. It also causes the shell to treat access to a variable
that has not been defined as an error, instead of silently subtituting
the empty string like it does by default.
Both these changes make debugging and shell programming in general MUCH
easier. You do, however, need to change a few things. You can't test if
a variable is empty with:
if test "$var" -ne ""; then
fi
for example; instead, you must use:
if test "${var:-}" -ne ""; then
fi
If you're just trying to set a default if a variable isn't defined (say,
the second argument) you might write something like:
destfilename="${2:-defaultname}"
To handle -e, you must make sure to explcitly handle expected failure
cases. For example:
# Delete `fred' if it exists
rm fred >&/dev/null
should become (and should be anyway)
rm -f fred
Creating a directory if it doesn't exist should really be:
if ! test -d "$thedir"; then
mkdir "$thedir"
fi
(Note that if $thedir exists, but is not a directory, we fail and abort
the script. You can of course change your chosen behaviour as
appropriate for your needs ... using -e just forces you to think about
it more).
You should also become familiar with the `-x' option to the shell, which
traces the execution of your script. For example:
#!/bin/sh
if test $# -eq 0; then
echo "usage: $0 blah [ blah [ blah ...] ]"
exit 1
fi
i=0
for arg in "$@"; do
(( i++ ))
echo "Argument $i: $arg"
done
when run normally shows:
[craig at albert ~]$ sh demo.sh fred123 "a b c d"
Argument 1: fred123
Argument 2: a b c d
and with sh -x:
[craig at albert ~]$ sh -x demo.sh fred123 "a b c d"
+ test 2 -eq 0
+ i=0
+ for arg in '"$@"'
+ (( i++ ))
+ echo 'Argument 1: fred123'
Argument 1: fred123
+ for arg in '"$@"'
+ (( i++ ))
+ echo 'Argument 2: a b c d'
Argument 2: a b c d
I'm sure you can see how that's useful in debugging.
--
Craig Ringer
More information about the plug
mailing list