2015-10-10 136 views
2

我正在尝试在重命名脚本中将连续的四位数字添加到文件名的末尾。我遇到的问题是,它只填充第一个文件,添加的数字不是顺序的。这里是我的脚本至今:在文件名的末尾添加连续数字 - Shell脚本

开始的文件名:

FILE-1.png 
FILE-5.png 
FILE-14.png 
FILE-99.png 
FILE-167.png 
FILE-199.png 
FILE-278.png 
FILE-455.png 

脚本:

a=`printf '%04d' "1"` 

cd /${1-$PWD} 

for i in *.png; 
    do mv $i `printf output.%04d.$a.png $(echo $i | sed 's/[^0-9]*//g')`; 
    let a=a+1 
done 

编辑: 我改剧本有点纳入顶部的fmt变量。但我仍然希望它按照第一组数字的数字顺序来命名第二组数字,如下面的我希望的输出中所示。

fmt=output.%04d 
n=1 

cd /${1-$PWD} 

for i in *.png; 
    do mv $i `printf $fmt.%04d.png $(echo $i | sed 's/[^0-9]*//g') "$n"`; 
    n=$((n+1)) 
done 

我的新的输出:

output.0001.0001.png 
output.0005.0007.png 
output.0014.0002.png 
output.0099.0008.png 
output.0167.0003.png 
output.0199.0004.png 
output.0278.0005.png 
output.0455.0006.png 

原始输出:

output.0001.0001.png 
output.0005.7.png 
output.0014.2.png 
output.0099.8.png 
output.0167.3.png 
output.0199.4.png 
output.0278.5.png 
output.0455.6.png 

所需的输出:

output.0001.0001.png 
output.0005.0002.png 
output.0014.0003.png 
output.0099.0004.png 
output.0167.0005.png 
output.0199.0006.png 
output.0278.0007.png 
output.0455.0008.png 

一如往常的任何帮助深表感谢!

+2

不知道为什么有人低估了这一点。它具有一个好问题的所有要素 - 输入,期望和实际输出,甚至尝试编码解决方案。 – ghoti

回答

1

所以..你使用printf进行格式化。这是一个好的开始。但是你没有持续使用它。没有格式化的部分..为什么不只是格式化呢?

#!/bin/sh 

fmt="output.%04d.%04d.png" 

cd /${1-$PWD} 

n=1 
for file in *.png; do 
    fn="${file%.*}"; fn="${fn#*-}" 
    mv "$file" "$(printf "$fmt" "$fn" "$n")" 
    n=$((n+1)) 
done 

注意循环中的第一行简单地脱掉一切从点到终点,然后通过从开始到仪表板起飞的一切剥离数出$file,第一。如果您的文件没有按照您的问题进行实际格式化,则必须调整此设置。

哦,感恩节快乐。 :-)每评论


UPDATE

以上的*.png显然会责令按字母顺序的东西,这样你FILE-5.png如下FILE-455.png扩展等

有许多工具可以帮助你获得“自然”排序顺序。特别是,如果您使用Linux,您的lssort可能来自GNU coreutils,这意味着您可以使用ls -vsort -V来获得自然排序顺序。但是你没有指定你在使用Linux,除此之外,还有parsing ls is a bad idea。但是bash的内部模式匹配和路径名扩展并不能处理自然类型。

这种特殊情况下,因为你正在处理(至少在你的问题)具有高度可预测格式的文件名,我们可以放心地可能解析ls输出,并使用命令行工具排序。

shopt -s extglob 
ls -v FILE-+([0-9]).png | while read file; do 

这台bash的extglob外壳选项,然后使用ls -v(这是Linux的相关性)来显示限制:

如果你正在使用Linux和bash,上面for线可以被替换文件的视图。在解析ls时,您不想因为*.png这样的结构出错,因为您不需要花时间预测文件名中是否存在换行符会发生什么情况。

如果你使用的是FreeBSD或OSX,或者不使用bash,需要额外的措施,因为有ls -v和Almquish外壳没有extglob

ls -f FILE-*.png | egrep '^FILE-[0-9]+\.png$' | sort -t- -k2n | while read file; do 
    if [ ! -f "$file" ]; then 
    continue 
    fi 

这种分解如下:

  • ls -f确实目录上的排序。 filespec有点限制了这个视图。
  • grep用于强制执行文件名格式,因为此模式不能在shell扩展中完全表示。
  • sort -t- -k2n用连字符分隔字段,然后在第二个字段上进行数字排序。
  • 循环内部的if确保我们有人不会通过创建像FILE-1.png\nFILE-2.png这样的文件名来搞砸我们。
+0

感谢您的帮助,但它似乎没有按照要求工作。在第10行中,我实际上切换了“$ n”和“$ fn”的顺序,但是得到了这个: 'output.0001.testing4d.pngoutput.0001.testing4d.png' 请注意脚本另存为testing.sh所以它将脚本名称以某种方式并入重命名中。 – VanCityGuy

+0

另一件事是它不是让他们连续: 'output.0001.testing4d.pngoutput.0001.testing4d.png' 'output.0005.testing4d.pngoutput.0007.testing4d.png' 'output.0014。 testing4d.pngoutput.0002.testing4d.png' 'output.0099.testing4d.pngoutput.0008.testing4d.png' 'output.0167.testing4d.pngoutput.0003.testing4d.png' 'output.0199.testing4d。 pngoutput.0004.testing4d.png' 'output.0278.testing4d.pngoutput.0005.testing4d.png' 'output.0455.testing4d.pngoutput.0006.testing4d.png' – VanCityGuy

+1

'fmt = '在我已经修复的脚本的顶部的一行;第二个'%'被替换为'$'。几天来一直没有找到我的眼镜,抱歉让我感到困惑。不确定发生了什么事,这是顺序的; 'for'行上的路径名扩展,'* .png'应该按字母/数字顺序匹配文件。再次尝试修复'fmt'行,看看结果是否如你所期望的那样。 – ghoti

相关问题