如何在 Bash 脚本中的目录名称中找到最新的时间戳?

如何在 Bash 脚本中的目录名称中找到最新的时间戳?

我有一些带时间戳的目录,其前缀可能有所不同,时间戳采用方便的 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}//'

所以:

  1. 使用以下方式列出文件find
  2. 使用以下命令将文件名中的最后 2 个_分隔字段添加到文件名的开头awk
  3. 对其进行排序(-V- 版本 sort - 可以处理诸如0A和之类的字段1
  4. 删除添加的部分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 行(-print0find-zsedsort)。awk被替换为等效sed命令。

相关内容