2

Currently, I am trying to parse out all the files inside a directory. I have a find function, but it appears to not be able to parse in file directories with whitespaces into a loop. Here, "$DIR" is the directory I wish to search in. Does anyone have any ideas how I can modify it to work? thanks.

for file in $(find "$DIR" -type f)
do
   echo "$file"
done
user321627
  • 263
  • 1
  • 6

3 Answers3

5

You don't need to for loop this.

find "$dir" -type f

will by default output all found objects.

You can make this explicit with:

find "$dir" -type f -print

If you really want to iterate over these, use a null separator and xargs:

find "$dir" -type f -print0 | xargs -0 -n1 echo

Or find's own -exec:

find "$dir" -type f -exec echo "{}" \;
DopeGhoti
  • 73,792
  • 8
  • 97
  • 133
  • If I wanted to pass the filenames found into a function, is there a standard way to do it? – user321627 Jun 08 '18 at 17:49
  • I'd read the results of `find` into an array (`arr=( $( find [...] ) )`), and reference that array within the function, or pass its contents _to_ the function `func "${arr[@]}"`. – DopeGhoti Jun 08 '18 at 17:52
  • 1
    @DopeGhoti isn't that going to have the same word-splitting issues as the original? See for example [How to pass files found by find as arguments?](https://unix.stackexchange.com/a/318429/65304) – steeldriver Jun 08 '18 at 19:18
  • Yeah, probably. Let me revise. I'd probably pass the directory to the function, and let it handle the `find`ing. – DopeGhoti Jun 08 '18 at 21:49
5

find ... | xargs ... and find ... -exec ... are both better options than this: to use a shell loop to iterate over find results correctly, we must use a while read loop:

while IFS= read -d '' -r filename; do 
    echo "$filename"
done < <(find "$dir" -type f -print0)

A lot to unpack there:

  • we use a Process Substitution to execute the find command and be able to read from the results like it's a file.
  • To read a line of input verbatim, the bash idiom is IFS= read -r line. That allows arbitrary whitespace and backslashes to be read into the variable.
  • read -d '' uses the null byte (as produced by -print0) as the end-of-line character instead of newline.
glenn jackman
  • 84,176
  • 15
  • 116
  • 168
4

You should not parse the output of find for the same reasons you shouldn't parse ls

Try using find/exec instead:

find "$DIR" -type f -exec echo {} \;
Kusalananda
  • 320,670
  • 36
  • 633
  • 936
jesse_b
  • 35,934
  • 12
  • 91
  • 140