Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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

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

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:


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
Alternative to get the above output: ls -d */ | xargs -I{} echo 'x='{} – Floris May 10 '14 at 19:43
Don't parse ls! – Braiam May 10 '14 at 23:30
Very true, @Floris. Guess you're no sheep, huh? – mikeserv May 11 '14 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 '14 at 19:11
@Floris - yes, it is a compliment. – mikeserv May 11 '14 at 19:15
up vote 15 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"

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 '14 at 14:48
It's a directory just by virtue of matching the */ glob, I think? – steeldriver May 10 '14 at 14:51
@Kevin */ only matches directories (and symlinks to directories). – Gilles May 10 '14 at 16:45
That worked. Thank you very much. – Wags May 10 '14 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 '14 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"
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 '14 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 '14 at 3:51
Whats a CW - what does that mean? – mikeserv May 11 '14 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 '14 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 '14 at 4:11

Your Answer


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.