cd to folder with spaces - in a script

Steven W. Orr steveo at syslang.net
Fri May 22 20:09:08 UTC 2009


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1


On Thursday, May 21st 2009 at 13:40 -0000, quoth Michael Casey:

=>How can I cd into a dir, when it contains spaces, and I need to use it in a
=>script?
=>
=>the directory:
=>/home/user/this is a folder/something
=>
=>normally I would use:
=>cd /home/user/this\ is\ a\ folder/something/
=>
=>but in a script I cant just add the "\"
=>like:
=>
=>find . -type d | while read FOLDER; do cd $FOLDER; done
=>$ No such file or directory
=>
=>the problem is, that there would be more "special chars" then spaces, "sed"
=>them all? :D
=>
=>Thank you

I saw that you got your question answered, but I just didn't like any of 
them. I'm feeling crabby today so I'll just explain it the way I want and 
no one else has to actually read it.

mkdir Hello\ there

- From there you can say:
cd Hello\ there
or
cd 'Hello there'
or 
cd "Hello there"

You can not say

cd "Hello\ there"
bash: cd: Hello\ there: No such file or directory

Think about what you're quoting and go from there.

Your next question is different. You want to to generate a list of 
directories and then do something in them.

I do NOT recommend the following construct
find . -type d | while read FOLDERNAME; do $(cd "$FOLDERNAME"); done

When you run the read command with one argument, you cause all words to be 
placed into a list who's name is FOLDERNAME. The problem is that you 
should be in charge of what you think a word really is.

Watch what happens when you do this:

535 > for ii in $(find . -maxdepth 1 -type d)
> do
> echo $ii
> done
./Hello
there
536 > 

This is a hint that you're probably doing it wrong.

Your better method when accessing files which may contain embedded spaces 
is to do (something like) this:

find . -maxdepth 1 -type d -print0 \
	| while read -d $'\000' xx ; do echo $xx ; done

In this case -d option is telling the read command that the delimiter is 
specifically the nul character and the -print0 is telling find to produce 
it's output with a nul character as the terminator instead of a newline.

Usually you see the -print0 used with xargs -0

a la

find . -maxdepth 1 -type d -print0 | xargs -0 -n 1 echo


In addition, let's go back to the previous method that I didn't like and 
slash at it some more:
find . -type d | while read FOLDERNAME; do $(cd "$FOLDERNAME"); done

If you look at the process structure of this, you should be aware that 
there are potential pros and cons going on. On the one hand, the while 
read loop is just one process, but the act of putting parens around the cd 
command causes the content of the parens to be executed in the context of 
its own subshell. You're counting on that so that when you're done with 
the command, you will be back where you started. On the other hand, if you 
set any variables WHICH YOU THINK ARE LOCAL in your while loop, they will 
not be visible to your script. For example:

ii=0
find . -type d |\
	 while read FOLDERNAME do $(cd "$FOLDERNAME; ii=$((ii+1))"); done
echo $ii

This will print out a big fat zarro, even if you processed 100 
directories. Why? Because the increment to ii will walways be done to the 
copy in the child; pipes make children. This may be acceptable, but if it 
isn't, then a way to prevent this from happening might be to use process 
substitution.

ii=0
while read -d $'\000' FOLDERNAME
do
    savd=$PWD
    cd "$FOLDERNAME"
    ii=$((ii+1))
    cd "$savd"
done <(find . -type d -print0)

This way you don't actually run your commands in a child and you still get 
to modify local variables.

I betcha you didn't realize just how cranky I really was.

- -- 
Time flies like the wind. Fruit flies like a banana. Stranger things have  .0.
happened but none stranger than this. Does your driver's license say Organ ..0
Donor?Black holes are where God divided by zero. Listen to me! We are all- 000
individuals! What if this weren't a hypothetical question?
steveo at syslang.net
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.10 (GNU/Linux)

iEYEARECAAYFAkoXBmwACgkQRIVy4fC+NyRyjgCeLHVs9xWf8IKP4iVbdNKbNA3z
fp0AniCzco+MibMzb/3bo0dvD1BTwb9Y
=6ReG
-----END PGP SIGNATURE-----




More information about the fedora-list mailing list