我想遍历一个文件列表。这个列表是一个find命令的结果,所以我想出了:

getlist() {
  for f in $(find . -iname "foo*")
  do
    echo "File found: $f"
    # do something useful
  done
}

这很好,除非文件名称中有空格:

$ ls
foo_bar_baz.txt
foo bar baz.txt

$ getlist
File found: foo_bar_baz.txt
File found: foo
File found: bar
File found: baz.txt

我能做些什么来避免空格分割?


当前回答

你可以用基于行的迭代替换基于单词的迭代:

find . -iname "foo*" | while read f
do
    # ... loop body
done

其他回答

好的,这是我在Stack Overflow上的第一篇文章!

Though my problems with this have always been in csh not bash the solution I present will, I'm sure, work in both. The issue is with the shell's interpretation of the "ls" returns. We can remove "ls" from the problem by simply using the shell expansion of the * wildcard - but this gives a "no match" error if there are no files in the current (or specified folder) - to get around this we simply extend the expansion to include dot-files thus: * .* - this will always yield results since the files . and .. will always be present. So in csh we can use this construct ...

foreach file (* .*)
   echo $file
end

如果你想过滤掉标准的点文件,那很简单…

foreach file (* .*)
   if ("$file" == .) continue
   if ("file" == ..) continue
   echo $file
end

在这个线程的第一篇文章中的代码将这样写:-

getlist() {
  for f in $(* .*)
  do
    echo "File found: $f"
    # do something useful
  done
}

希望这能有所帮助!

find . -name "fo*" -print0 | xargs -0 ls -l

见xargs先生。

另一个解决工作的方法是……

目标是:

递归地选择/过滤目录中的文件名 处理每个名称(路径…中的任意空格)

#!/bin/bash  -e
## @Trick in order handle File with space in their path...
OLD_IFS=${IFS}
IFS=$'\n'
files=($(find ${INPUT_DIR} -type f -name "*.md"))
for filename in ${files[*]}
do
      # do your stuff
      #  ....
done
IFS=${OLD_IFS}


你可以用基于行的迭代替换基于单词的迭代:

find . -iname "foo*" | while read f
do
    # ... loop body
done

Find有一个-exec参数,循环查找结果并执行任意命令。例如:

find . -iname "foo*" -exec echo "File found: {}" \;

这里{}表示找到的文件,将其包装在""中允许生成的shell命令处理文件名中的空格。

在很多情况下,你可以替换掉最后一个\;(它开始一个新命令)和\+,这将把多个文件放在一个命令中(不一定是所有的,但要了解更多细节,请参阅man find)。