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