Need Scripting Help
Cameron Hutchison
camh+ubuntu at xdna.net
Mon Jan 10 01:39:19 UTC 2005
Once upon a time David M. Carney said...
>
> As the script is written, it works just fine on any file with no
> spaces in the filename. However, it fails with any files with spaces
> in the filename.
>
> #!/bin/bash
> #
> for I in `echo $*`
> do
> exec gnome-terminal --command="bcrypt "$I
> done
change this to:
for I in "$@"
do
exec gnome-terminal --command="bcrypt \"$I\""
done
There are three places in this script where you need to be aware of
spaces in filenames.
1) for I in `echo $*`
After `echo $*` is expanded, the for loop will split it on space
boundaries. This will break file names with spaces. Furthermore,
`echo $*` is redundant, since just $* will do the same without invoking
another process.
Put quotes around the $* and the spaces in filenames will be
preserved. eg. "$*". Finally, use "$@" which is similar to "$*" but
technically more correct - see the bash man page for differences.
2) Expansion of $I in the loop
After getting word expansion correct in the argument list to the "for"
command, you need to expand the variable properly. This almost always
entails enclosing the expansion in double quotes: "$I", otherwise the
spaces will not be preserved. In a simpler case than yours, if the loop
contained:
ls -l $I
and the filename was "foo bar", the command would expand to:
ls -l foo bar
which would try to list two separate files. So you need:
ls -l "$I"
which expands to
ls -l "foo bar"
Sometimes you dont notice the difference because it can be subtle. For
example: I="foo bar" (two spaces):
echo $I -> echo foo bar
This outputs "foo bar" (one space) unless you enclose $I in double
quotes.
3) Expansion of arguments by gnome-terminal
When gnome-terminal runs it's command, you need quotes in the right
places otherwise it will break filenames with spaces. You need to escape
the quotes so the "exec" command in the for loop does not consume the
quotes. gnome-terminal will then get a single argument that contains:
--command=bcrypt "foo bar"
If those quotes weren't there, bcrypt would think there were to files to
encrypt.
All in all, spaces in filenames are a real pain to handle properly with
the shell, particularly when you have multiple levels of evaluation like
you have Often when writing scripts like this, it takes me a little
trial and error to get everything right. Dont be put off if you dont get
it first go.
More information about the ubuntu-users
mailing list