我想遍历一个文件列表。这个列表是一个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有一个-exec参数,循环查找结果并执行任意命令。例如:

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

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

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

其他回答

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

见xargs先生。

在某些情况下,如果您只需要复制或移动一个文件列表,您也可以将该列表管道到awk。 重要的是$0字段周围的\"" "" \"(简而言之,您的文件,一行列表=一个文件)。

find . -iname "foo*" | awk '{print "mv \""$0"\" ./MyDir2" | "sh" }'
find . -iname "foo*" -print0 | xargs -L1 -0 echo "File found:"

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

目标是:

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

#!/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}


还有一个非常简单的解决方案:依赖bash globbing

$ mkdir test
$ cd test
$ touch "stupid file1"
$ touch "stupid file2"
$ touch "stupid   file 3"
$ ls
stupid   file 3  stupid file1     stupid file2
$ for file in *; do echo "file: '${file}'"; done
file: 'stupid   file 3'
file: 'stupid file1'
file: 'stupid file2'

注意,我不确定这个行为是默认的,但我在我的商店里没有看到任何特殊的设置,所以我会说它应该是“安全的”(在osx和ubuntu上测试过)。