Bash scripting and files with spaces in them

I’ve decided to post this one as it’s one of those things that I have come across so often but each time I froget the solution. The problem arises when you are trying to script using the for command and you run up against filenames that have spaces. No matter what way you try and quote them the for command will split them out. Assume we have two files in a directory. One with spaces in it’s name and one without.

ken@berta:~/x$ ls -1
file-name-one.txt
file name two.txt

Say we want to rename the files using the mv command. We could use the following for loop:

ken@berta:~/x$ for FILE in *.txt;do mv ${FILE} ${FILE}.bak;done
mv: target `two.txt.bak’ is not a directory
ken@berta:~/x$ ls -1
ken@berta:~/x$ file-name-one.txt.bak
ken@berta:~/x$ file name two.txt

There was no problem with the first file as it has no spaces. Rather than passing one variable “file name two.txt” to the mv command, the for command split it up into three separate variables using the space character as a delimiter. What this actually expanded to was this:

ken@berta:~/x$ mv file name two.txt file name two.txt.bak
mv: target `two.txt.bak’ is not a directory

Here the move command (mv) is trying to move all the files named ‘file’, ‘name’, ‘two.txt’, ‘file’ and ‘name’ into a directory called ‘two.txt.bak’. Obviously the files don’t exist but as the mv command first checks for the existance of the destination directory ‘two.txt.bak’, it gives the error that there is no directory by that name.

I’ve found a few ways to get around this but the one I like the best is to use the while loop instead. The while loop is nice as you can also use it to read in from a text file.

ken@berta:~/x$ ls -1
file-name-one.txt
file name two.txt
ken@berta:~/x$ ls -1 *.txt| while read FILE;do mv -v “${FILE}” “${FILE}”.bak ;done
`file-name-one.txt’ -> `file-name-one.txt.bak’
`file name two.txt’ -> `file name two.txt.bak’
ken@berta:~/x$ ls -1
file-name-one.txt.bak
file name two.txt.bak
ken@berta:~/x$

Here we pipe the output of the ls command into the while command loop. You need to put the double quotes around the variable or it will be treated as multiple variables.

This entry was posted in General and tagged . Bookmark the permalink.

3 Responses to Bash scripting and files with spaces in them

  1. Pingback: kenfallon.com » Blog Archive » Quick and dirty filename cleanup

  2. Rob says:

    This is great. I was trying in bash to move a filename with all sorts of special characters. The ls -1 loop worked great. Thanks!

  3. Stuart says:

    Thanks very much – I was pulling my hair out trying to get a mv with spaces working – I’ll have to write this in my really useful doc! 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *