目前我正在编写一个 bash 脚本,该脚本应该按创建日期的顺序循环遍历目录中的某些文件。为此,我使用(使用真实代码而不是echo
):
for i in $(ls -tr)
do
echo $i
done
大部分时间都工作得很好。
但现在我发现了一种破坏脚本的文件类型:aha_-_a ()a.txt
.
该文件名包含一个空格,后跟一个左括号“(”,这似乎会触发换行符。结果是:
aha_-_a
()a.txt
但应该是:
aha_-_a ()a.txt
您知道如何获得所需的行为吗?
答案1
不加$(ls -tr)
引号会在扩展时调用 split+glob。
拆分是根据字符$IFS
(默认为 SPC、TAB 和 NL)完成的,然后 glob 部分将在其中查找通配符并尝试扩展与相应模式匹配的文件。
在这里,看起来您实际上只想拆分ls
NL 字符的输出,而不执行 glob 部分。所以应该是:
IFS=$'\n' # split on NL only
set -o noglob # disable the glob part
for f in $(ls -tr); do
printf '%s\n' "$f"
done
这样对于包含 SPC 字符的文件就可以正常工作了。然而,如果文件名带有 NL 字符,它仍然不起作用。
在这里,最好是切换到zsh
并执行以下操作:
for f in *(NOm); do
printf '%s\n' "$f"
done
where*
扩展到当前目录中的所有非隐藏文件,按年龄反向排序,就像ls -rt
使用Om
glob 限定符一样(如果没有匹配文件,N
则 (for ) 可以避免错误)。nullglob
或者如果你有 GNU ls
,则bash
:
eval "files=($(ls --quoting-style=shell-always -rt))"
for f in "${files[@]}"; do
printf '%s\n' "$f"
done