Daniel Borek
Daniel Borek

Reputation: 13

bash listing subfolders in current folder doesn't give expected results [gives only first folder]

I try to list subfolders and save them as list to a variable

DIRS=($(find . -maxdepth 1 -mindepth 1 -type d ))

After that I want to do some work in subfolders. i.e.

for item in $DIRS
 do     
echo $item

But after

echo $DIRS

it gives only first item (subfolder). Could someone point me to error or propose another solution?

Upvotes: 1

Views: 68

Answers (1)

John1024
John1024

Reputation: 113924

The following creates a bash array but lists only one of three subdirectories:

$ dirs=($(find . -maxdepth 1 -mindepth 1 -type d ))
$ echo $dirs
./subdir2

To see all the directories, you must use the [@] or [*] subscript form:

$ echo "${dirs[@]}"
./subdir2 ./subdir1 ./subdir3

Or, using it in a loop:

$ for item in "${dirs[@]}"; do echo $item; done
./subdir2
./subdir1
./subdir3

Avoiding problems from word splitting

Note that, in the code above, the shell performs word splitting before the array is created. Thus, this approach will fail if any subdirectories have whitespace in their names.

  1. The following will successfully create an array of subdirectory names even if the names have spaces, tabs or newlines in them:

    dirs=(*/)
    
  2. If you need to use find and you want it to be safe for difficult file names, then use find's --exec option.

Documentation

The form $dirs returns just the first element of the array. This is documented in man bash:

Referencing an array variable without a subscript is equivalent to referencing the array with a subscript of 0.

The use of [@] and [*] is also documented in man bash:

Any element of an array may be referenced using ${name[subscript]}. The braces are required to avoid conflicts with pathname expansion. If subscript is @ or , the word expands to all members of name. These subscripts differ only when the word appears within double quotes. If the word is double-quoted, ${name[]} expands to a single word with the value of each array member separated by the first character of the IFS special variable, and ${name[@]} expands each element of name to a separate word.

Upvotes: 1

Related Questions