需要逐个处理当前目录中的文件。我正在寻找一种方法,将
ls
或 find
命令的输出结果作为数组元素存储起来,这样我就可以根据需要操作数组元素。arr=( $(find /path/to/toplevel/dir -type f) )
$ find . -type f
./test1.txt
./test2.txt
./test3.txt
$ arr=( $(find . -type f) )
$ echo ${#arr[@]}
3
$ echo ${arr[@]}
./test1.txt ./test2.txt ./test3.txt
$ echo ${arr[0]}
./test1.txt
然而,如果你只想逐个处理文件,你可以使用 find
的 -exec
选项(如果脚本比较简单),或者像下面这样循环遍历 find
返回的结果:
while IFS= read -r -d $'\0' file; do
# stuff with "$file" here
done < <(find /path/to/toplevel/dir -type f -print0)
read -r -d $'\0'
告诉 read
命令不将反斜杆视为特殊转义字符,并使用 NUL 字符作为定界符来分隔每个单词,因为我们告诉 find
使用 -print0
作为定界符。 IFS=
部分实质上取消了特殊的内部字段分隔符环境变量,因此它不会对制表符、空格或新行执行单词拆分操作。简而言之,这些命令使您可以遍历任何文件名,无论它包含什么类型的字符。 - SiegeXIFS=
移到 while 前面,这样行得通吗:IFS = ; while ...
? - user2066805find ... | while ....
之间有什么区别吗? - user2066805for i in `ls`; do echo $i; done;
再简单不过了!
编辑:根据Dennis Williamson的评论,似乎您可以!
编辑2:尽管OP特别询问如何解析ls
的输出,但我只想指出,正如下面的评论者所说,正确的答案是“不要这样做”。改用for i in *
或类似方法。
for i in *
这个命令甚至更简单! - Dennis Williamsonfor i in *; do ...
执行相同的操作,但它不会被文件名中的奇怪字符所困扰,并且运行得更快(因为它不会生成另一个进程)。 - Gordon Davisson*
:for in in $path/*
? - PHP Learnerfor f in "$path"/*
- Dennis Williamsonfor i in *; do echo "$i" done
在一个空目录中会输出 *
。 - Alois Mahdal*
,这意味着“如果没有文件”),shell glob扩展会保留glob。在许多情况下,这会导致“找不到文件”的类型错误,如果这是您想要的结果,则无妨。但如果这在您的脚本中是个问题,可以在其前面使用 shopt -s nullglob
(并在后面使用 shopt -u nullglob
以避免以后出现问题),或者在循环中添加 if [[ ! -e "$i" ]]; then continue; fi
,这样它就会跳过不存在的文件。 - Gordon Davisson您实际上不需要使用ls/find来查找当前目录中的文件。
只需使用for循环:
for files in *; do
if [ -f "$files" ]; then
# do something
fi
done
如果您想处理隐藏文件,您可以设置相应的选项:
shopt -s dotglob
这个命令只适用于bash。
%files
应该改为 $files
。另外,如果您使用的是 Bash 4.X 版本,可以设置 shopt -s globstar
并使用 for files in **; do
来进行递归操作,完全不需要使用 find
命令。 - SiegeX根据您想要做什么,您可以使用xargs:
ls directory | xargs cp -v dir2
cp
支持,你可以使用xargs cp -v --target-directory dir2
。 - Dennis Williamsonfind ... -print0 | xargs -0
可以解决这个问题。它到底出了什么问题?对我来说它是有效的。 - Dennis Williamson