获取数组中基于子字符串的唯一文件名列表

时间:2018-12-28 13:59:15

标签: bash shell

我有一个目录my_dir,其文件名为:

a_v5.json
a_v5.mapping.json
a_v5.settings.json
f_v39.json
f_v39.mapping.json
f_v39.settings.json
f_v40.json
f_v40.mapping.json
f_v40.settings.json
c_v1.json
c_v1.mapping.json
c_v1.settings.json

我正在寻找一种在bash中获取数组[a_v5, f_v40, c_v1]的方法。在这里,我需要具有最新版本号的文件名数组。

对此进行了尝试:ls *.json | find . -type f -exec basename "{}" \; | cut -d. -f1,但它返回的结果不是.json扩展名的文件。

4 个答案:

答案 0 :(得分:2)

如果文件名不包含空格和*?之类的特殊符号,则可以使用以下命令:

array=($(
    find . -type f -iname \*.json |
    sed -E 's|(.*/)*(.*_v)([0-9]+)\..*|\2 \3|' |
    sort -Vr | sort -uk1,1 | tr -d ' '
))

这很丑陋而且不安全。以下解决方案更长,但可以处理所有文件名,即使其中包含换行符也是如此。

maxversions() {
    find -type f -iname \*.json -print0 |
    gawk 'BEGIN { RS = "\0"; ORS = "\0" }
        match($0, /(.*\/)*(.*_v)([0-9]+)\..*/, group) {
            prefix = group[2];
            version = group[3];
            if (version > maxversion[prefix])
                maxversion[prefix] = version
        }
        END {
            for (prefix in maxversion)
                print prefix maxversion[prefix]
        }'
}
mapfile -d '' array < <(maxversions)

在两种情况下,您都可以使用array检查declare -p array的内容。

答案 1 :(得分:1)

数组和bash字符串解析。

tata

或者,如果您愿意,

declare -A tmp=()
for f in $SOURCE_DIR/*.json
do f=${f##*/}        # strip path
   tmp[${f%%.*}]=1   # strip extraneous data after . in filename
done
declare -a c=( $( printf "%s\n" "${!tmp[@]}" | cut -c 1 | sort -u ) ) # get just the first chars
declare -a lst=( $( for f in "${c[@]}"
                    do printf "%s\n" "${!tmp[@]}" |
                         grep "^${f}_"            |
                         sort -n                  |
                         tail -1; done ) )
echo "[ ${lst[@]} ]"
[ a_v5 c_v1 f_v40 ]

答案 2 :(得分:0)

这是完成此操作的一种可能方法:

arr=( $(  { for name in $( ls {f,n,m}*.txt );  do echo ${name:0:1} ; done; } | sort | uniq ) )

输出:

$ echo ${arr[0]}
f

$ echo ${arr[1]}
m

$ echo ${arr[2]}
n

致谢!

答案 3 :(得分:0)

AWK解决方案

这不是一个很好的解决方案...我对awk的了解有限。 您应该找到此功能。

我已对此进行了更新,以删除@socowi建议的过时的uniq。 我还包括了@socowi建议的printf版本。

ls *.json | cut -d. -f1 | sort -rn |  awk -v last="xx" '$1 !~ last{ print $1; last=substr($1,1,3)  }'

OR

printf %s\\n *.json | cut -d. -f1 | sort -rn | awk -v last="xx" '$1 !~ last{ print $1; last=substr($1,1,3)  }'

下面的旧理解

查找具有名称匹配模式的文件。

现在选择第二个字段,因为您的结果可能类似于./

find . -type f -iname "*.json" | cut -d. -f2

要获取唯一的标题。...

find . -type f -iname "*.json" | cut -d. -f2 | sort | uniq