批量重命名未知名称和未知扩展名的文件

批量重命名未知名称和未知扩展名的文件

我有一堆照片,有些是.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

相关内容