如何按文件名而不是完整的相对路径对子目录 glob 进行排序

如何按文件名而不是完整的相对路径对子目录 glob 进行排序

给定一个像这样的文件树:

subdirFoo/2019-06-01-blah.ext
subdirFoo/2019-06-07-blah.ext
subdirFoo/2019-05-02-blah.ext
subdirBar/2019-06-03-blah.ext
subdirBar/2019-05-05-blah.ext
subdirBar/2019-05-13-blah.ext

我想迭代这些文件并将它们作为参数传递给somecommand,但是,我想按文件名而不是完整路径的排序顺序迭代它们。

通常,glob 按字母顺序排序,但我按以下顺序获取它们:

subdirBar/2019-05-05-blah.ext
subdirBar/2019-05-13-blah.ext
subdirBar/2019-06-03-blah.ext
subdirFoo/2019-05-02-blah.ext
subdirFoo/2019-06-01-blah.ext
subdirFoo/2019-06-07-blah.ext

也就是说,在排序时考虑了子目录,这不是我想要的。

如何让 glob 仅按文件名排序,但仍将子目录保留在循环中,以便命令可以正确引用文件?即剥离子目录将不起作用,因为文件的路径不正确/丢失。

即我需要按以下顺序排列它们:

subdirFoo/2019-05-02-blah.ext
subdirBar/2019-05-05-blah.ext
subdirBar/2019-05-13-blah.ext
subdirFoo/2019-06-01-blah.ext
subdirBar/2019-06-03-blah.ext
subdirFoo/2019-06-07-blah.ext

首选 zsh 中的解决方案,但我可以接受 bash 或 sh。

答案1

您可以使用sort需要将字段分隔符设置为/,并在第二个字段上排序。

答案2

我不知道是不是正确的方法,但您可以将${VAR##*/}参数替换填充到 glob 限定符中zsh oe

 % printf '%s\n' subdir*/*(.Noe:'REPLY=${REPLY##*/}':)
subdirFoo/2019-05-02-blah.ext
subdirBar/2019-05-05-blah.ext
subdirBar/2019-05-13-blah.ext
subdirFoo/2019-06-01-blah.ext
subdirBar/2019-06-03-blah.ext
subdirFoo/2019-06-07-blah.ext

这将按最后一个路径组件(文件名)对 glob 结果进行排序。 glob 限定符中的位:'...':针对每个匹配执行,并REPLY设置为将用作排序键的值($REPLY是从一开始的实际匹配)。

例如,参见全球预选赛的小节zsh:14.7 文件名扩展

oe 和 o+ 是特殊情况;它们各自后跟 shell 代码,分别按照 e glob 限定符和 + glob 限定符进行分隔(见上文)。针对每个匹配的文件执行代码,参数 REPLY 设置为条目上的文件名,并将 globsort 附加到 zsh_eval_context。代码应该以某种方式修改参数 REPLY。返回时,使用参数的值而不是文件名作为要排序的字符串。与其他排序运算符不同,oe 和 o+ 可以重复,但请注意,任何 glob 表达式中可能出现的任何类型的排序运算符的最大数量为 12。

答案3

我最终使用find而不是 glob。感谢 @ctrl-alt-delor 提供有关按字段排序的提示。

for file in `find {subdirFoo,subdirBar} -maxdepth 1 -name 'prefix*.ext' | sort -t / -k 2`; do echo $file; somecommand $file; done

相关内容