looping through files with spaces in the filenames in bash
I sometimes have to transfer files with spaces in the names, I like using a for loop, but the usual way doesn’t work.
Usual way:
for file in `find . -type f|grep .ext$`
do
/do/something/to $file
done
To get around this I use a while loop with a read instead. Using the read will read to the end of the line, enclosing within quotes escapes the spaces.
Unusual way:
find . -type f|grep .ext$ |while read file
do
/do/something/to "$file"
done
Or if you don’t like using more than one line…and enjoy the unreadable (I’m transferring all my avi files to another computer in this example)
find . |grep .avi$ |while read file; do scp "$file" 172.16.1.1:; done



June 5th, 2007 at 14:32
Thank you, thank you, thank you. I’ve been racking my brain trying to get this to work with a “for file in …” loop with no success. This helps a lot.
December 7th, 2007 at 06:26
This really really helps.. thank you brotha.
August 15th, 2008 at 03:11
Many thanks for this. I have been writing shell scripts for 20 years and got stuck. I tried many different ways (xargs etc) and was about to resort to a Tcl script.
November 5th, 2008 at 05:03
Thank you so much!
April 14th, 2009 at 16:10
Thanks for that. Just what the doctor ordered.
May 1st, 2009 at 11:50
I have struggled with spaces in pathnames forever using bash. This is like on of the best tips ever…
Thanks a million !
Solved the BBEdit backup folder problem..
find /BACKUP_MAIN/BBEdit_Backups -type f \( -name ‘*.txt’ -o -name ‘*.applescript’ \)|while read file
do
# echo “$file”
mdimport -d 1 /Library/Spotlight/SourceCode.mdimporter “$file”
# mdimport -d 1 /Library/Spotlight/OSAImporter.mdimporter “$file”
done
May 1st, 2009 at 12:15
I had the wrong path in my previous message.
I have struggled with spaces in pathnames forever using bash.
This is like one of the best tips ever…
Thanks a million !
Solved the BBEdit backup folder problem..
find ~/Documents/BBEdit\ Backups -type f \( -name ‘*.txt’ -o -name ‘*.applescript’ \)|while read file
do
# echo “$file”
mdimport -d 1 /Library/Spotlight/SourceCode.mdimporter “$file”
# mdimport -d 1 /Library/Spotlight/OSAImporter.mdimporter “$file”
done
May 11th, 2009 at 09:00
Interstingly this method still fails with spaces at the end of the file. FYI, however I just did the changes maually since it reduced the number of misses from hundreds to 4. Thanks this is better than the environemtn variable that you can change to get the for loop to work.
July 8th, 2009 at 21:55
I’ve searched before for a solution like this. It’s relatively simple, elegant, and I’m pained that it doesn’t seem to be more well known. Thanks.
October 7th, 2009 at 10:00
I love you. This has bothered me for ages!
December 5th, 2009 at 08:28
Thanks. In my case, I had a list of filenames, so:
cat list | while read file
do
doSomething $file
done
December 6th, 2009 at 13:34
[...] To loop through files that have spaces in the name, try the following example from narrabilis.com [...]
March 5th, 2010 at 09:22
Awesome — HUGE thanks!
March 18th, 2010 at 07:14
[...] was soll ich sagen, nach einer stundenlangen Ausprobier-Orgie und Google-Recherchen habe ich hier den passenden Denkanstoß gefunden. #!/bin/bash find . -name "*.srt" | while read [...]
April 14th, 2010 at 15:08
You could also use the bash input field separator. Just prepend it to whatever your usual way is. Default is all whitespace.
Example:
IFS=”
“
for file in `find . -type f|grep .ext$`
do
/do/something/to $file
done
April 21st, 2010 at 05:06
Thank you! Glad this came up in a google search, was really scratching my head.
May 24th, 2010 at 05:25
Well, what do you say. Tried to solve it my self for an hour or so, then found it on google “I’m feeling lucky”. Thank you very much.
My problem: Find files in a directory structure, file names can include spaces, create symbolic names in the current directory.
The files are CA root certificates, link names should be the certificate hash. (a Sendmail + TLS configuration issue)
cd /etc/mailcerts/CA
find . -name *pem -print0 | while read -d $” file
do
ln -s “$file” `openssl x509 -noout -hash < "$file"`.0
done
May 24th, 2010 at 05:30
For some reasons, qoute characters are missing in my previous post in the code string..
June 11th, 2010 at 07:32
What a simple and elegant solution for something that has bugged me for ages.
Life-Saver!