我想遍历一个文件列表。这个列表是一个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

其他回答

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

find . -iname "foo*" | awk '{print "mv \""$0"\" ./MyDir2" | "sh" }'

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

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

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

目标是:

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

#!/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做任何其他类型的过滤,你可以使用以下bash 4.0:

shopt -s globstar
getlist() {
    for f in **/foo*
    do
        echo "File found: $f"
        # do something useful
    done
}

**/将匹配零个或多个目录,因此完整模式将匹配当前目录或任何子目录中的foo*。

我真的很喜欢for循环和数组迭代,所以我想我会把这个答案添加到混合…

我也喜欢marchelbling愚蠢的文件示例。:)

$ mkdir test
$ cd test
$ touch "stupid file1"
$ touch "stupid file2"
$ touch "stupid   file 3"

在test目录中:

readarray -t arr <<< "`ls -A1`"

这将每个文件列表行添加到名为arr的bash数组中,并删除任何尾随换行符。

假设我们想给这些文件取一个更好的名字……

for i in ${!arr[@]}
do 
    newname=`echo "${arr[$i]}" | sed 's/stupid/smarter/; s/  */_/g'`; 
    mv "${arr[$i]}" "$newname"
done

$ {!arr[@]}扩展到0 1 2,因此"${arr[$i]}"是数组的第i个元素。变量周围的引号对于保留空格很重要。

结果是三个重命名的文件:

$ ls -1
smarter_file1
smarter_file2
smarter_file_3