linux - 如何在每个父目录中打印最后一个目录

标签 linux shell perl unix

我有一组目录和子目录如下。

aaa/180809_1047
aaa/180915_0055
aaa/181012_1545
aaa/xyz
bbb/180809_1047
bbb/180915_0055
bbb/181012_1545
bbb/181105_0000
bbb/xyz
.
.
.
zzz/180821_1555
zzz/181004_2355
zzz/xyz

大部分子目录都是 YYMMDD_HHMM 格式。在这里,我试图从每个父目录中打印格式为 YYMMDD_HHMM 的子目录(最新)。以下是我的要求。

输出:

aaa/181012_1545
bbb/181105_0000
zzz/181004_2355

我使用了如下的查找命令:

find ./*/ -type d -maxdepth 1 -mindepth 1 -name "???????????" | sort -u | tail -1

"????????????" --> 这是打印符合格式 YYMMDD_HHMM 的目录。

执行此命令后,我只得到了。

zzz/181004_2355 

最佳答案

我会使用 for 循环在 bash 中本地执行此操作,而不是使用 find

老实说,我不记得 bash 是否对处理 glob 的顺序做出任何 promise 。因此,使用您包含的示例日期,这是一个使用 [[:

比较文件的单行代码
$ declare -A last=(); for a in *; do for b in $a/[0-9]*/; do [[ $b > $last[$a] ]] && last[$a]=$b; done; done; declare -p last
declare -A last=([bbb]="bbb/181105_0000/" [zzz]="zzz/181004_2355/" [aaa]="aaa/181012_1545/" )

请注意,这里的限制模式是$a/[0-9]*/,这对您的示例数据来说已经足够了。当然,您可以根据需要限制它,使用字符类并消除 glob。

另请注意,此模式中的尾随 / 可确保您只会匹配属于目录的内容。这会将 / 放在 $last 数组中每个结果的末尾。如果需要,您可以进行后处理:

$ for i in "${!last[@]}"; do last[$i]="${last[$i]%/}"; last[$i]="${last[$i]#*/}"; done
$ declare -p last
declare -A last=([bbb]="181105_0000" [zzz]="181004_2355" [aaa]="181012_1545" )

为了便于阅读,这里将一行分成多行。 :)

# Create an associative array. Requires bash 4+.
declare -A last=()

# Step through the top-level directories
for a in *; do
  # Step through the second level directories
  for b in "$a"/[0-9]*/; do
    # Compare and record as required
    [[ $b > $last[$a] ]] && last[$a]="$b"
  done
done

# Print the result
declare -p last

关于linux - 如何在每个父目录中打印最后一个目录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53149509/

相关文章:

linux - Bash 代码块语法着色

bash - 用于测试的shell脚本

bash - 如何在 shell 中等待文件创建并监听其内容直到超时

image - 仅比较纯图像数据和图像相似度的重复照片搜索?

regex - perl 正则表达式匹配子串

windows - Perl 模块手册安装 Windows XP

python - 如何编写 python 脚本来读取文件并返回版本

java - 测量 Linux 中的内存使用情况

linux - 无法在 bash 中输入日期变量

linux - 排序命令中空格的处理。 LC_COLLATE=c 和 LC_COLLATE ="en_US.UTF-8"之间的区别