Wednesday, November 29, 2006

Another geeky Linux post

Here's a trick I learned today when writing Bash scripts in Linux, when I had to work out how to deal with spaces in filenames when running a for loop.

Normally, to do some operation on every file in a directory I'd use a loop like this:

for file in $(ls -1 --color=no *.mp3);
do
rm $file;
done
(which would delete every file in the directory in a ridiculously roundabout fashion)

But... this time I had filenames with spaces in them, which means that the rm command would be seeing something like:
rm filename with spaces.dat
and so tries to delete "filename", "with", and "spaces.dat" which don't exist. The first thing I tried doing to avoid this was to quote the $file variable, to preserve the spaces:
rm "$file";
But that didn't work! After poking around a bit I discovered that the problem is with the "for" statement: it assigns each word in the argument to the variable not each line, as I wanted it to. This can be fixed by using while and read instead of for:
ls -1 --color=no | while read file;
do
rm $file;
done
Works like a very charming old charm!

No comments: