Never been to CodeSnippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world (or not, you can keep them private!)

Handling filenames with spaces in a bash for or while loop (See related posts)

// The `find` here gets every directory in my home dir, one level deep, but some of them have spaces... the default 'for i in $(find ...)' behavior treats each individual word boundary as a separate variable, but piping to `read` breaks them on newlines
// Note: OS X `find` does not support "-depth 1" (its -depth opt is for depth-first searching vs. breadth-first), just use an 'ls' with an 'if [ -d $filename]' to test for directories

find ~ -type d -depth 1 | while read filename; do
# ls ~ | while read filename; do
	echo $filename
	# other stuff
done

Comments on this post

Araxia posts on Jun 28, 2007 at 19:47
In bash, you can just set the internal field separator (IFS) to not include spaces and you'll be able to use paths with spaces in them, e.g.

#!/bin/bash
FOOBAR="/System/Library/Screen Savers/"
echo "Test #1 with default IFS:"
ls ${FOOBAR}
ORIGINAL_IFS=$IFS
IFS=$'\n'
echo ""
echo "Test #2 with modified IFS:"
ls ${FOOBAR}
IFS=$ORIGINAL_IFS
echo ""
echo "Test #3 with restored IFS:"
ls ${FOOBAR}


Note that the $ before the '\n' is just so the \n sequence is treated as a single character.
chochem posts on May 26, 2008 at 11:39
I've used this method quite a lot (as well as the mentioned in the other comment) but have problems with both:
The 'read' method means AFAICT that you cannot use the read or select command _within_ the while loop. So if you need user input on what to do with the files/lines, you're screwed.
The IFS method is a neat trick but what if you need to use a for loop to handle items separated by spaces within the bigger loop? In theory, I guess you can keep switching between various IFS values but I haven't got that to work in practice.
So if I may suggest a humble while loop, where you manually advance a counter to point to the next line in the file list/text file/whatever it is you're processing one- line-at-a-time:

i=0
numberoflines=$(cat mytextfile.txt | wc -l)
while [ $i -lt $numberoflines ]; do
let i++
contentoflinenumberi="$(sed -n ${i}p mytextfile.txt)"
read -p "Do you wish to see line ${i}? (y/n) " reply
if [ "$reply" = "y" ]; then
echo "$contentoflinenumberi"
fi
done

You need to create an account or log in to post comments to this site.