递归地收集特定目录中的所有文件

递归地收集特定目录中的所有文件

我有一个项目,有很多目录,其中包含扩展名为.strings.

这些文件是多种语言的本地化版本。

例如,我可能有 3 个同名文件,例如,MyView.strings但每个文件都位于本地化目录中,例如en.lprojit.lprojpt-PT.lproj。项目结构中有数百个这样的目录。

我正在创建一个 bash 脚本来按语言列出所有这些文件所在的目录。

示例:我想扫描目录结构并查找en.lproj该结构可能具有的所有目录,并列出这些目录内所有文件的完整路径。

就此而言,这样的命令将在终端窗口上发挥作用

find . -type d -name "en.lproj" -print  

但是如何将这样一个命令的结果存储到一个数组中,以便稍后在 bash 脚本中枚举?

我试过这个

result=($(find . -type d -name "en.lproj" -print))

但因为路径包含空格,所以数组在该空格上被破坏,并且我期望结果是一个数组,其中每行都是一个路径,包含或不包含空格。

我使用的是 macOS BigSur。

答案1

要将命令的输出存储为数组,您需要:

array=( $(command) )

但是,shell 会根据 的值拆分命令的结果$IFS。由于这通常设置为空格、制表符和换行符,这意味着如果您使用的命令返回名称中包含任何这些字符的文件名,则数组将为名称的每个部分都有一个单独的元素。为了显示:

$ touch 'a file with spaces'
$ ls
'a file with spaces'

$ array=( $( find . -type f) )

$ for f in "${array[@]}"; do echo "FF: $f"; done
FF: ./a
FF: file
FF: with
FF: spaces

在您的情况下,如果所有文件都有简单的名称,没有空格,您可以这样做(不需要-print,这是默认操作):

files=( $(find . -type d -name "en.lproj") )

但是,为了安全起见,您可以重新定义$IFS此命令,以确保适用于任何文件名(包含换行符的文件名除外):

$ IFS=$'\n' array=( $( find . -type f) )
$ for f in "${array[@]}"; do echo "FF: $f"; done
FF: ./a file with spaces

如果您需要能够处理任意文件名,包括带有换行符的文件名,您可以使用mapfile分隔符并将其设置为 null,还可以使用 (不可移植,但受 GNU 和 BSD 支持find,因此它应该在您的 mac 上工作)使用空分隔符而不是换行符打印结果-print0的选项:find

mapfile -d '' array < <(find . -type f -print0)

这将处理任何类型的文件:

$ touch 'a bad
file'
$ ls
'a bad'$'\n''file'  'a file with spaces'

$ mapfile -d '' array < <(find . -type f -print0)
$ for f in "${array[@]}"; do echo "FF: $f"; done
FF: ./a file with spaces
FF: ./a bad
file

相关内容