Bash for ls 循环在“(”字符处分割行

Bash for ls 循环在“(”字符处分割行

目前我正在编写一个 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 部分将在其中查找通配符并尝试扩展与相应模式匹配的文件。

在这里,看起来您实际上只想拆分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

这样对于包含 SPC 字符的文件就可以正常工作了。然而,如果文件名带有 NL 字符,它仍然不起作用。

在这里,最好是切换到zsh并执行以下操作:

for f in *(NOm); do
  printf '%s\n' "$f"
done

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

相关内容