使用Bash重命名分数顺序中的文件

时间:2015-09-16 02:25:55

标签: bash file sorting

我是一名专业音乐家,经常需要重命名20-30个.PDF文件列表,以便按照分数顺序排序。例如,我有一个文件列表,如:

Rolling Thunder Eb Clarinet  - 4p.PDF
Rolling Thunder Flute 1 - 4p
Rolling Thunder Flute 2 - 4p
Rolling Thunder FULL SCORE - CONDENSED - 20p
Rolling Thunder Horn in F 1 - 3p
Rolling Thunder EDIT 9-7-15 Horn in F 2 - 3p
...

我需要将它们重命名,以便按照它们出现在分数中的顺序排序(在Finder中),即:

00 - Rolling Thunder FULL SCORE - CONDENSED - 20p
01 - Rolling Thunder Flute 1 - 4p
02 - Rolling Thunder Flute 2 - 4p
... etc.

我通过创建一个包含工具顺序的文本文件(以便根据需要修改各种上下文的顺序)来解决这个问题,例如:

Piccolo
Flute
Oboe
Clarinet
Bassoon
French Horn
...

然后启动Bash脚本以按此顺序查找文件:

while read line; do 
find . -name "*$line*" 
done < scoreorder.txt

我不确定如何在此基础上重命名文件。有人可以帮忙吗?

1 个答案:

答案 0 :(得分:1)

假设目录中没有不相关的文件,可能是这样的。

要获取所有PDF文件的列表,只需printf匹配的glob。

printf '%s\n' *.pdf

让我们将其传递给Awk脚本,该脚本将这些脚本映射到scoreorder.txt的索引号。首先,将文件读入数组a,并为我们读取的每个条目添加数字索引。

awk 'NR==FNR { a[++n] = $0; next } ...' scoreorder.txt -

当我们阅读NR==FNR时,scoreorder.txt将成立;脚本的其余部分将应用于我们从标准输入读取的行,来自上面的printf

... { m=0;
    for(i=1; i<=n; ++i)
        if ($0 ~ a[i])
            if (m==0 || length(a[m]) < length(a[i])) m=i;

在每一行上,我们从最长匹配中选择索引(因此French Horn优先于Horn,无论它们在索引中的位置如何)。如果没有匹配,m将为0。

    printf("%i\t%s\n", m, $0); }'

这将产生“原始排序”,其中FULL SCORE将具有前缀00(因为它与任何关键字都不匹配),例如Flute文件的前缀为02.这足以对列表进行排序。

| sort -n |

现在我们只需要对行进行编号并稍微进行后处理以删除“原始排序”数字。

awk -F '\t' '{ printf "mv \"%s\" \"%02i - %s\"\n", $2, NR, $2 }'

此时的排序顺序仍略有偏差 - 第二个EDIT文件名中的Horn会使排序顺序失效。也许你只想修改你的命名约定,或者你想在.pdf之前选择最后的数字作为辅助排序键。

输出是一个shell脚本,一旦你对它做了它应该做的事情感到满意就可以输出到sh。这仍然是最后的剧本。

printf '%s\n' *.pdf |
awk 'NR==FNR { a[++n] = $0; next }
    { m=0;
        for(i=1; i<=n; ++i)
            if ($0 ~ a[i])
                if (m==0 || length(a[m]) < length(a[i])) m=i;
    printf("%i\t%s\n", m, $0); }' scoreorder.txt - |
sort -n |
awk -F '\t' '{ printf "mv \"%s\" \"%02i - %s\"\n", $2, NR, $2 }'

如果您的文件名包含双引号,制表符或换行符,则会变得更加棘手。我只是假设你没有。