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
是的。这是使用find
and 循环的众所周知的问题之一。
解决这个问题的一种简单方法是将找到的列表转储到 stdout 中read
:
find ~/Documents/ -type f |
while IFS= read -r filename
do
date -r "$filename" # ... or any other command using $filename
done
如果你的命令足够小,你可以使用-exec
key 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
,它与-print0
POSIX 不同并且可移植,并且还可以很好地处理任意文件名:
$ find . -type f -exec date -r {} \;
Fri May 12 04:53:06 PM BST 2023
Fri May 12 04:51:42 PM BST 2023