我有一堆照片,有些是.jpg
,有些是.png
。任何给定的图片都可以有一个完全随机的名称(可能包括空格)。在任何给定的目录中,如何重命名所有目录,同时保持扩展名不变?输入,例如:
001.jpg 02.png 05.png zzzz.jpg
我想将他们的名字完全替换为四位数,从 开始0001
,一直到9999
(如果需要)。因此,输出可能如下所示:
0001.jpg 0002.png 0003.png 0004.jpg
这些文件的顺序对我来说很重要,但如果我仅按文件名对它们进行排序,它们就已经按顺序排列了。
我已经检查了 perl rename
,在这个例子中它的用法对我来说是个谜。
答案1
Perl解决方案
perl -e '
@files = sort glob "*.png *.jpg";
for(@files){
($extension = $_) =~ s/.*\.(.*)/$1/;
$new_name = sprintf("%04d",++$counter).".$extension";
die "File $new_name already exists and would be clobbered\n" if -e $new_name;
rename $_ => sprintf("%04d",++$counter).".$extension"
}'
重击解决方案
export COUNT=0
find . -maxdepth 1 -name "*.jpg" -o -name "*.png" -print0 | xargs -0 sort | while read file do\
extension=${file##*.}\
COUNT=$((COUNT+1))\
mv -- "$file" $(printf "%04d" $COUNT).$extension\
done
笔记
这两种解决方案都是未经测试的 Bash 解决方案:首先在虚拟文件上尝试它们。- 如果文件名中包含换行符,Bash 解决方案可能会崩溃。
- 危险:正如 Gilles 在下面的评论中指出的那样,如果原始文件之一的名称遵循目标命名约定,那么它最多会被重命名为另一个“数字”,最坏的情况会被另一个文件破坏。发生哪一种情况取决于它相对于其他文件的排序方式。我在 Perl 解决方案中为此添加了一项规定,因为这是 OP 似乎赞成的规定。
- Perl 解决方案(实施了上述规定)是非幂等。
答案2
(bash
解决方案)
用于printf
格式化新名称并awk
选择文件扩展名...
$ ls
a.b c.d e.f g.h i.j k.l m.n o.p q.r s.t this file.y u.v w.x
$ COUNTER=0
$ for i in *; do COUNTER=$(($COUNTER + 1)); mv -v "$i" $(printf "%04g" $COUNTER).$(echo $i | awk -F'.' '{print $NF}'); done
`a.b' -> `0001.b'
`c.d' -> `0002.d'
`e.f' -> `0003.f'
`g.h' -> `0004.h'
`i.j' -> `0005.j'
`k.l' -> `0006.l'
`m.n' -> `0007.n'
`o.p' -> `0008.p'
`q.r' -> `0009.r'
`s.t' -> `0010.t'
`this file.y' -> `0011.y'
`u.v' -> `0012.v'
`w.x' -> `0013.x'
$i
正如您所提到的,请记住将输入用引号括起来以转义文件名中的空格。
答案3
在TXR口齿不清:
(let ((counter 0))
(each ((name (sort (glob "*.{png,jpg}"))))
(let ((new (pic "0###<" (inc counter) (short-suffix name))))
(if (path-exists-p new)
(error `@new already exists`))
(rename-path name new))))
我们可以做一些其他的事情,比如首先准备重命名列表,检查右侧名称是否同时存在,在这种情况下不执行任何重命名。
答案4
保存这个脚本:
#!/bin/bash
NUM=0
NUMBER_LENGTH=4
cd $1;
ls . -1 | sort | while read file; do
NUM=$(( $NUM + 1 ));
PREFIX=$NUM;
while [ ${#PREFIX} != $NUMBER_LENGTH ]; do
PREFIX="0${PREFIX}";
done;
NEW_NAME=$PREFIX.`echo $file | sed 's|[^.]\+\.\([\A-Za-z0-9]\+\)|\1|g'`;
mv "$file" "$NEW_NAME";
done
并将其执行为:
./_scriptname_ _dirWhereYourStuffIs_
注意:不要将脚本放在您的东西所在的同一目录中,因为脚本本身将被重命名。
如果你足够疯狂,你可以在一行中完成这一切(不使用脚本):
NUM=0; NUMBER_LENGTH=4; ls . -1 | sort | while read file; do NUM=$(( $NUM + 1 )); PREFIX=$NUM; while [ ${#PREFIX} != $NUMBER_LENGTH ]; do PREFIX="0${PREFIX}"; done; NEW_NAME=$PREFIX.`echo $file | sed 's|[^.]\+\.\([\A-Za-z0-9]\+\)|\1|g'`; mv "$file" "$NEW_NAME"; done
注意事项 #2:对于这一行,我假设您正在使用 BASH