bash for 循环与 GNU "ls -v" 顺序相同("version-number"排序)



在bash脚本中,我想做一个典型的"for file In somedir",但我希望文件的处理顺序与"ls-v"返回文件的顺序相同。我知道使用"ls"作为函数的缺点。有没有办法在不使用"ls"的情况下复制"-v"?谢谢

假设这是"版本号"排序顺序,这也是由GNUsort实现的。因此,在GNU平台上:

somedir=/foo
while IFS= read -r -d '' filename; do
printf 'Processing file: %qn' "$filename"
done < <(set -- "$somedir"/*; [[ -e $1 || -L $1 ]] && printf '%s' "$@" | sort -z -V)

如果真的想使用for循环而不是while循环,那么解析成一个数组并迭代:

files=( )
while IFS= read -r -d '' filename; do
files+=( "$filename" )
done < <(set -- "$somedir"/*; [[ -e $1 || -L $1 ]] && printf '%s' "$@" | sort -z -V)
for filename in "${files[@]}"; do
printf 'Processing file: %qn' "$filename"
done

解释上面的一些魔术:

  • < <(...)中,<(...)过程替换。它被替换为一个文件名,当从中读取时,该文件名将返回所附代码的输出。因此,< <(...)将把该过程替换的输出作为while read循环的输入。BashFAQ#1中描述了这种循环形式。使用这种重定向而不是管道进入循环的原因在BashFAQ#24中给出
  • set -- "$somedir"/*"$somedir"/*的结果替换当前上下文中的参数列表(该上下文是运行进程替换的子shell!);因此,变量somedir中命名的目录的内容(默认为非隐藏)
  • 只有当该glob扩展到至少一个项时,[[ -e $1 || -L $1 ]]才为真;如果它仍然是*(并且不存在以该名称命名的实际文件系统对象),则在此条件下选通输出将阻止进程替换发出任何输出
  • sort -z告诉sort用NUL(文件名中不允许存在的字符)来分隔输入和输出中的元素

最新更新