[lug] bash scripting question

Tkil tkil at scrye.com
Sun Nov 20 05:27:47 MST 2005


>>>>> "Hugh" == Hugh Brown <hugh at math.byu.edu> writes:

Hugh> for i in *;do command "$i"; done

Interesting that this is actually more robust than the "read" version.
Consider:

| $ touch "a b" "c d"
| $ perl -e 'open $fh, ">", "sneaky\nfile" or die "open: $!";
|            print $fh "boo!";'
| $ ls 
| a b  c d  old  sneaky?file

Using "read" doesn't work, because of that newline in "sneaky\nfile":

| $ ls -1 | while read file ; do echo "<$file>" ; done
| <a b>
| <c d>
| <old>
| <sneaky>
| <file>

But the "for i in *" construct works fine:

| $ for file in * ; do echo "<$file>" ; done
| <a b>
| <c d>
| <old>
| <sneaky
| file>

Note to newbies: this is why "find ... -print0" and "xargs -0 ..." are
always safer than the just plain "-print"; the latter relies on
newlines (which are legal in unix filenames) instead of forcing NUL
characters (which aren't; NUL and '/' are the only two characters that
are forbidden at the filesystem level).

Personally, as soon as I hit any quoting/splitting issue in shell that
can't be solved with simple addition of double quotes, I just bail and
go to perl where I know the rules.  I'll have to remember this trick,
though, as just this last week I ran into this situation.

Happy hacking,
t.




More information about the LUG mailing list