String 在Bash中从文件名中提取最后一个数字
我有很多文件要重命名。几乎所有这些文件都是图片 源文件名类似于:String 在Bash中从文件名中提取最后一个数字,string,bash,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
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张图片)
所以我想得到字符串,从第一个出现的至少两个数字开始,从点后面的右边直到第一个非数字字符。如果右边只有一个数字,则应忽略该文件
for x in ./*.JPG ./*.jpg; do
y=$(echo "$x"|sed '/[^0-9]//g');
echo "$x" "$y";
done
虽然我没有给你最后的答案,但这应该让你开始,并说明如何处理你描述的任务的技巧
根据以后要对文件执行的操作,还可以组合find
和grep
,例如find-键入f | grep-v'\.[0-9]\.
以筛选包含\
的所有文件,该文件后跟一个数字,后跟一个点(未测试,可能需要转义)-v
用于否定由grep
过滤的匹配项
因为在你的帖子中,你告诉过你要重命名过滤器,并提供了一个过滤一些文件的例子,我猜你需要两者:首先,过滤你不想要的文件,然后在for
循环中重命名过滤过的文件
sed -nr 's%^.*[^0-9]([0-9]{2,}\.[^.]+)$%\1%p' < <(find ./ -type f -iname '*.JPG')
虽然我没有给你最后的答案,但这应该让你开始,并说明如何处理你描述的任务的技巧
根据以后要对文件执行的操作,还可以组合find
和grep
,例如find-键入f | grep-v'\.[0-9]\.
以筛选包含\
的所有文件,该文件后跟一个数字,后跟一个点(未测试,可能需要转义)-v
用于否定由grep
过滤的匹配项
因为在你的帖子中,你告诉过你要重命名过滤器,并提供了一个过滤一些文件的例子,我猜你需要两者:首先,过滤你不想要的文件,然后在for
循环中重命名过滤过的文件
sed -nr 's%^.*[^0-9]([0-9]{2,}\.[^.]+)$%\1%p' < <(find ./ -type f -iname '*.JPG')
虽然我没有给你最后的答案,但这应该让你开始,并说明如何处理你描述的任务的技巧
根据以后要对文件执行的操作,还可以组合find
和grep
,例如find-键入f | grep-v'\.[0-9]\.
以筛选包含\
的所有文件,该文件后跟一个数字,后跟一个点(未测试,可能需要转义)-v
用于否定由grep
过滤的匹配项
因为在你的帖子中,你告诉过你要重命名过滤器,并提供了一个过滤一些文件的例子,我猜你需要两者:首先,过滤你不想要的文件,然后在for
循环中重命名过滤过的文件
sed -nr 's%^.*[^0-9]([0-9]{2,}\.[^.]+)$%\1%p' < <(find ./ -type f -iname '*.JPG')
虽然我没有给你最后的答案,但这应该让你开始,并说明如何处理你描述的任务的技巧
根据以后要对文件执行的操作,还可以组合find
和grep
,例如find-键入f | grep-v'\.[0-9]\.
以筛选包含\
的所有文件,该文件后跟一个数字,后跟一个点(未测试,可能需要转义)-v
用于否定由grep
过滤的匹配项
因为在你的帖子中,你告诉你要重命名过滤器,并提供了一个过滤一些文件的例子,我猜你需要两个:首先,过滤你不想要的文件,然后在
for
循环中重命名过滤过的文件。sed-nr's%^.[^0-9]([0-9]{2,}.[^.]+)$%\1%p<sed-nr's%^.[^0-9]([0-9]{2,}.]$%\1%p'<sed-nr's%^.[^0-9]([0-9]{2,}.[^.]+)$%\1%p'<sed-nr's%^.[^0-9]([0-9]{2,}.[^.]+)$\1%p'<这里有一个使用sed
的方法,可以提高性能:
sed -nr 's%^.*[^0-9]([0-9]{2,}\.[^.]+)$%\1%p' < <(find ./ -type f -iname '*.JPG')
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
输出:
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
下面是一种使用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
输出:
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
下面是一种使用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
输出:
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
下面是一种使用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
输出:
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
对于600000个文件,这肯定会失败,因为您将超过命令行的最大长度:在我的机器上,getconf ARG_MAX
outputs2097152
,并且文件至少有5个字符,因此对于600000个文件,这已经超过了最大长度。此外特别是在这里,您真的不需要ls
!查看您的命令:首先shell看到大括号并展开它;剩下的是ls*.JPG*.JPG
;然后,它执行路径名扩展并尝试将其馈送到ls
!没用!无论如何,ls
会用它做什么?它将对参数进行排序并输出它们。您也可以这样做:printf'%s\n'*.{JPG,JPG}
。现在,globs在shell中速度很慢,因此使用find
的方法更合适。关于如何获取文件的新名称的基本问题已经得到了回答。我迭代文件夹中的文件(每天一个文件夹)结构:2013/12/31/bildxxx.jpg,并将它们放置在一个新的结构中,并使用新的名称。@gniourf_gniourf我希望大多数Shell会从stdin中逐行读取命令。你是在暗示那场狂欢吗