从Bash中的文件名中提取最后一个数字

时间:2015-03-05 13:08:13

标签: string bash

我有很多要重命名的文件。几乎所有这些文件都是图片。

源文件名类似于:

DSC08828.JPG       => 08828.JPG
20130412_0001.JPG  => 0001.JPG
0002.JPG           => 0002.JPG
IMG0047.jpg        => 0047.jpg
DSC08828_1.JPG     => Is a duplicate should be ignored
...
DSC08828_9.JPG     => Is a duplicate should be ignored

我想做的就是以尽可能快的方式获取最后一个数字后跟文件扩展名(因为我们正在谈论近600.000张图片)

所以我想从第一个出现的字符串开始,从第一个出现的点到右边的第一个非数字字符。如果右边只有一个数字,则应忽略该文件。

3 个答案:

答案 0 :(得分:1)

for x in ./*.JPG ./*.jpg; do
    y=$(echo "$x"|sed '/[^0-9]//g');
    echo "$x" "$y";
done

虽然我没有给你最后的答案,但这应该让你开始并说明如何处理你描述的任务的技术。

根据您之后要对文件执行的操作,您还可以合并findgrep,例如find . -type f | grep -v '_[0-9]\.',以过滤包含_的所有文件,然后一个数字,后跟一个点(未测试,可能需要转义)。 -v用于否定由grep过滤的匹配项。

因为在你的帖子中你告诉你要重命名过滤器并提供了一个过滤一些文件的例子,我猜你需要两个:首先,过滤你不想要的文件,然后重命名过滤for循环中的那些。

答案 1 :(得分:1)

sed -nr 's%^.*[^0-9]([0-9]{2,}\.[^.]+)$%\1%p' < <(find ./ -type f -iname '*.JPG')

在正则表达式处理中,SED比BASH快得多,所以尽可能使用它而不是=〜。

答案 2 :(得分:1)

这是一种使用sed的方法,可以提高效果:

ls *.{JPG,jpg} | \
sed '
    /_[1-9]*\./d;    # first drop any line that appears to be a duplicate   
    /^[0-9]*\./d;    # drop any line that does not need to be renamed   
    s/\(.*\)/\1 \1/; # save the original filename by duplicating the pattern space
    s/ .*_/ /;       # remove any leading characters followed by and including _ in the new filename
    s/ [A-Z]*/ /;    # remove any leading capital letters from the new filename
    s/^/mv -i /;     # finally insert mv command at the beginning of the line
'

如果您对这些命令感到满意,请转到sh

<强>输入:

0002.JPG
20130412_0001.JPG
DSC08828.JPG
DSC08828_1.JPG
DSC08828_9.JPG
IMG0047.jpg

<强>输出:

mv -i 20130412_0001.JPG 0001.JPG
mv -i DSC08828.JPG 08828.JPG
mv -i IMG0047.jpg 0047.jpg