for-do 循环不适用于包含空格的文件名

for-do 循环不适用于包含空格的文件名
for X in $(find ~/Documents/ -type f);do date -r "${X}";done

当“/Documents/”中的文件名不包含空格时,上面的行可以正常工作。
但是,如果文件名包含空格,则会出现以下错误:

 No such file or directory

如何使其适用于包含空格的文件名?

答案1

不要使用循环,使用-exec以下参数find

find ~/Documents/ -type f -exec date -r {} \;

答案2

是的。这是使用findand 循环的众所周知的问题之一。

解决这个问题的一种简单方法是将找到的列表转储到 stdout 中read

find ~/Documents/ -type f |
while IFS= read -r filename
do
    date -r "$filename"    # ... or any other command using $filename
done

如果你的命令足够小,你可以使用-execkey of find

find ~/Documents/ -type f -exec date -r '{}' \;

答案3

for你不能,这就是为什么你从不使用这种方式来循环返回文件名的命令的输出的原因之一。也称为Bash 陷阱第 1 号。如果您使用while循环,则可以很好地处理带有空格的文件:

$ ls
'a file with spaces'
$ find . -type f | while read -r X; do date -r "$X"; done
Fri May 12 04:51:42 PM BST 2023

但是,对于包含换行符的文件名,这仍然会失败:

$ touch "$(printf 'a file with\na newline')"
$ ls
'a file with'$'\n''a newline'  'a file with spaces'
$ find . -type f | while read -r X; do date -r "$X"; done
date: './a file with': No such file or directory
date: 'a newline': No such file or directory
Fri May 12 04:51:42 PM BST 2023

为了解决这个问题,并假设您的find实现支持它,您可以使用-print0打印以 null 结尾的行,然后使用使用 NUL 字节作为分隔符的循环。像这样:

$ find . -type f -print0 | while IFS= read -r -d '' X; do date -r "$X"; done
Fri May 12 04:53:06 PM BST 2023
Fri May 12 04:51:42 PM BST 2023

也就是说,到目前为止最好的方法是使用 find -exec,它与-print0POSIX 不同并且可移植,并且还可以很好地处理任意文件名:

$ find . -type f -exec date -r {} \;
Fri May 12 04:53:06 PM BST 2023
Fri May 12 04:51:42 PM BST 2023

相关内容