我有一些带时间戳的目录,其前缀可能有所不同,时间戳采用方便的 YYYYMMDD 格式,后跟不同的后缀,这些后缀也表示时间顺序(不是最合理的方式)。不幸的是,名称的标题部分可以包含_
用作字段分隔符的字符。
例如:
/collect/mydir_20161102_0A
/collect/mydir_20161102_0B
/collect/mydir_20161102_0C
/collect/mydir_20161102_1
/collect/mydir_20161102_2
/collect/other_dir_20161103_0A
/collect/other_dir_20161103_0B
/collect/mydir_20161104_0A
/collect/mydir_20161104_0B
/collect/mydir_20161104_0C
/collect/mydir_20161104_1
/collect/mydir_20161104_2
此处显示的名称顺序实际上是创建的时间顺序,包括后缀,因此 0A 在 0B 之前,所有 0 都在 1 之前。不应出现具有相同时间戳的不同标题前缀的情况。
目录自创建以来可能已经更改或修改,因此无法使用 ctime 和 mtime。
我需要输出包含标题和时间戳的字符串,带或不带前面的路径 somydir_20161104
或/collect/mydir_20161104
,但这必须始终来自最近的目录。搜索不应在目录级别中递归。
我也想避免解析ls
!
答案1
可能不太漂亮,而且我没有处理带有换行符的文件名:
find collect/ -mindepth 1 |
awk -F_ '{print $(NF-1),$NF,$0}' |
sort -V |
sed -r 's/^([^ ]* ){2}//'
所以:
- 使用以下方式列出文件
find
- 使用以下命令将文件名中的最后 2 个
_
分隔字段添加到文件名的开头awk
- 对其进行排序(
-V
- 版本 sort - 可以处理诸如0A
和之类的字段1
) - 删除添加的部分
sed
对于包含任何有效字符的文件名来说,它可以是安全的,但我必须用它awk
来替换sed
。
我的输出:
$ find collect/ -mindepth 1 | awk -F_ '{print $(NF-1),$NF,$0}' | sort -V | sed -r 's/^([^ ]* ){2}//'
collect/mydir_20161102_0A
collect/mydir_20161102_0B
collect/mydir_20161102_0C
collect/mydir_20161102_1
collect/mydir_20161102_2
collect/other_dir_20161103_0A
collect/other_dir_20161103_0B
collect/mydir_20161104_0A
collect/mydir_20161104_0B
collect/mydir_20161104_0C
collect/mydir_20161104_1
collect/mydir_20161104_2
当然,这只是解析ls
。;)
如果只需要标题和时间戳而不需要后缀,请反转排序(sort -Vr
)并将最后一个修改sed
为:
sed -r 's:.*/::;s/_[^_]*$//;q'
所以:
$ find collect/ -mindepth 1 | awk -F_ '{print $(NF-1),$NF,$0}' | sort -rV | sed -r 's:.*/::;s/_[^_]*$//;q'
mydir_20161104
还有一个可以处理带有换行符的文件名的版本:
find collect/ -mindepth 1 -print0 | sed -rz 's/(.*)(_[^_]*)(_[^_]*)$/\2\3 &/' | sort -zrV | sed -zr 's:.*/::;s/_[^_]*$//;q'
整个过程中使用\0
-delimited 行(-print0
在find
、-z
在sed
和sort
)。awk
被替换为等效sed
命令。