Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I am trying to feed Directory names into a for loop. My code is as follows:

td='/Test/TopDir/'
cd "$td" 
for x in $(ls -d */ | cut -f1 -d'/'); do
  echo x=$x
done

The top directory I run this on looks like this when running an ls command:

ls -l
drwxrwxrwx    4 Jason    users         4096 May  6 06:36 2014-02-02 - Jebby (
drwxrwxrwx    3 Jason    users         4096 May  6 06:09 2014-02-04 - Jebby (
drwxrwxrwx    2 root     root          4096 May  6 06:09 @eaDir
-rw-r--r--    1 Jason    users      3956225 Jan 26 10:17 DSC01062.JPG
-rw-r--r--    1 Jason    users      3927603 Jan 26 10:18 DSC01063.JPG

The results of my for loop is as follows:

x=2014-02-02
x=-
x=Jebby
x=(
x=2014-02-04
x=-
x=Jebby
x=(
x=@eaDir

As you can see the for loop is breaking the directory names into sub-pieces after each space. In this example I only want the For Loop to execute three time with the three directories:

  1. 2014-02-02 - Jebby (
  2. 2014-02-04 - Jebby (
  3. @eaDir

What am I doing wrong?

share|improve this question
1  
Alternative to get the above output: ls -d */ | xargs -I{} echo 'x='{} –  Floris May 10 at 19:43
5  
Don't parse ls! –  Braiam May 10 at 23:30
    
Very true, @Floris. Guess you're no sheep, huh? –  mikeserv May 11 at 15:52
    
@mikeserv - I am not sure what your comment means but I am going to assume it is a compliment? –  Floris May 11 at 19:11
1  
@Floris - yes, it is a compliment. –  mikeserv May 11 at 19:15

2 Answers 2

up vote 13 down vote accepted

Avoid parsing the output (or at least the filename portion) of ls in shell scripts if at all possible. It will always give issues with word-splitting where filenames contain whitespace.

If you want to iterate over directories you can do that using a simple shell glob i.e.

for d in */; do 
  echo "$d"
done

The ls command should only be used for displaying directory listings in human-readable form in the terminal.

share|improve this answer
    
You should also explain how to check if a file is a directory. –  Kevin May 10 at 14:48
    
It's a directory just by virtue of matching the */ glob, I think? –  steeldriver May 10 at 14:51
    
@Kevin */ only matches directories (and symlinks to directories). –  Gilles May 10 at 16:45
    
That worked. Thank you very much. –  Wags May 10 at 19:30
    
This is bad advice. It will have issues as long as you don't handle them. They can be handled. And besides, set -- */ is more useful than for ... in ... –  mikeserv May 11 at 1:31

Using @mikserv's suggestion, you can do

cd /Test/TopDir/
set -- "$PWD" */
cd /somewhere/else
td=$1 ; shift 
for x; do
  echo x="${td}/$x"
done
share|improve this answer
    
No. You dont need for ... in ... if its already in your $@array you can just do for ... - personally i like while ${1+:} false ; do though. –  mikeserv May 11 at 3:47
    
@mikeserv thanks, edited. I made this CW, so feel even freer than usual to add any other improvements. I just thought it was a good idea and should be here. –  terdon May 11 at 3:51
    
Whats a CW - what does that mean? –  mikeserv May 11 at 3:53
    
@mikeserv Community wiki, also see here. In short it's used to make posts into collaborative efforts that the community edits. An often useful side effect is that the author gets no rep from it. –  terdon May 11 at 3:56
    
There - maybe its a little clearer now why i said it was more useful. I guess you suckered me into doing the answer after all. –  mikeserv May 11 at 4:11

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.