基于名称前缀

时间:2017-01-04 19:56:57

标签: bash grep

我有一个问题是如何解决过去一个月我一直在努力解决的问题。场景如下:

我有一个基本目录,其中有多个子目录都遵循相同的子目录格式:

A/{B1,B2,B3}所有B*下都有pipeline/results/目录结构。

所有这些results目录中都包含多个*.xyz个文件。这些*.xyz文件具有基于其命名前缀的特定层次结构。命名前缀又取决于它们的处理距离。例如,它们可以是select.xyzselect.copy.xyzselect.copy.paste.xyz,其中的操作是selectcopypaste。我想做的是写一个ls | grepfind根据处理级别选择这些文件。

编辑:

处理渠道转为select - > copy - > paste。 “处理最多”的文件将是其中大部分阶段作为其文件名中的前缀的文件。即select.copy.paste.xyz的处理频率高于select.copy,后者的处理速度高于select.xyz

例如,假设

B1/pipeline/results/select.xyzselect.copy.xyz

B2/pipeline/results/select.xyz

B3/pipeline/results/select.xyzselect.copy.xyzselect.copy.paste.xyz

如何编写从每个子目录中选取处理最多的文件的ls | grep / find?这应该会给我B1/pipeline/results/select.copy.xyzB2/pipeline/results/select.xyzB3/pipeline/results/select.copy.paste.xyz

关于如何考虑方法的任何指针都会有所帮助。谢谢!

1 个答案:

答案 0 :(得分:1)

对于这个答案,我们将忽略目录结构的上半部分A/B{1,2,3}。即使目录为.../pipeline/results/,也会考虑某些A/B1/doNotIncludeMe/forbidden/pipeline/results目录中的所有文件。我们假设文件扩展名xyz是常量。

一个简单的解决方案是遍历目录并检查文件是否从后到前存在。也就是说,首先检查select.copy.paste.xyz是否存在。如果文件不存在,请检查是否存在select.copy.xyz,依此类推。这个脚本可能如下所示:

#! /bin/bash
# print paths of the most processed files

shopt -s globstar nullglob
for d in **/pipeline/result; do
    if [ -f "$d/select.copy.paste.xyz" ]; then
        echo "$d/select.copy.paste.xyz"
    elif [ -f "$d/select.copy.xyz" ]; then
        echo "$d/select.copy.xyz"
    elif [ -f "$d/select.xyz" ]; then
        echo "$d/select.xyz"
    else
        # there is no file at all
    fi
done

它完成了这项工作,但并不是很好。我们可以做得更好!

#! /bin/bash
# print paths of the most processed files

shopt -s globstar nullglob
for dir in **/pipeline/result; do
    for file in "$dir"/select{.copy{.paste,},}.xyz; do
        [ -f "$file" ] && echo "$file" && break
    done
done

第二个脚本与第一个脚本完全相同,但更容易维护,调整等等。这两个脚本都使用包含空格甚至换行符的文件和目录名称。

如果您的路径中没有空格,也可以使用以下(hacky,but loop-free)脚本。

#! /bin/bash
# print paths of the most processed files

shopt -s globstar nullglob
files=(**/pipeline/result/select{.copy{.paste,},}.xyz)
printf '%s\n' "${files[@]}" | sed -r 's#(.*/)#\1 #' | sort -usk1,1 | tr -d ' '