我有如下目录和子目录。
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命令:
find ./*/ -type d -maxdepth 1 -mindepth 1 -name "???????????" | sort -u | tail -1
"???????????"
->这将打印与YYMMDD_HHMM格式匹配的目录。
执行此命令后,我只会得到。
zzz/181004_2355
答案 0 :(得分:1)
我会使用for
循环而不是使用find
在bash中本地执行此操作。
老实说,我不记得bash是否对处理glob的顺序作出任何承诺。因此,使用包含的示例日期,这是一种使用[[
比较文件的单行代码:
$ 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
答案 1 :(得分:0)
您将使用tail -1
尾随命令的输出。因此,您只会得到最后一行。 :)
除了您的命令看起来正确之外。
加上其他注释:
find .
而不会出现全局错误,因为默认情况下find是递归的???????????
可能会更具限制性。选择??????_????
或使用[[:digit:]]
。答案 2 :(得分:0)
使用sort -u
和tail -1
的想法很好,并且与同一个父目录中的子目录列表一起使用时,它会起作用。 -u
将删除重复项,但这不是必需的,因为2个子目录在同一父目录中不能具有相同的名称。
?
表示任何字符;可以使用限制性更强的[0-9]
来选择一个数字。
尝试一下:
find . -maxdepth 1 -type d -print0 | xargs -0 sh -c '
for dir ; do
find "${dir}" -maxdepth 1 -type d \
-name '[0-9][0-9][0-1][0-9][0-3][0-9]_[0-2][0-9][0-6][0-9]' | sort | tail -1
done' dummy | sort
对于在第一级(第一个find . -maxdepth 1 ...
)中找到的每个目录:
[0-9][0-9][0-1][0-9][0-3][0-9]_[0-2][0-9][0-6][0-9]
(第二find
)sort
和
tail
命令) -print0
和-0
参数与sh -c
和for statement
一起使用,以使命令行对带有特殊字符(例如{{1 }}。
line break
未使用,但它是强制性的,请参见dummy
测试
man sh
答案 3 :(得分:0)
使用查找,排序和awk:
find -name '??????_????' -type d | sort -r | awk -F'/' '{if(!s[$(NF-1)]++) print $0}