给定一个像这样的文件树:
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