在文件名末尾重命名一堆带有日期修改时间戳的文件?

Inq*_*Kea 16 date rename files

所以,比如说,我有一个包含一堆文件的目录,比如 g.txt,其中 g.txt 上次修改是在 2012 年 6 月 20 日。

我将如何批量重命名所有文件(如 g.txt),最后修改日期为 2012 年 6 月 20 日?

cas*_*cas 22

这是 goldschrafe 单线的一个版本:

  • 不使用统计

  • 适用于早期版本的 GNU date

  • 正确处理文件名中的任何空格

  • 还处理以破折号开头的文件名

    for f in *; do mv -- "$f" "$f-$(date -r "$f" +%Y%m%d)"; done


更新 2021-03-20

我对这个问题的回答多年来一直困扰着我(好吧,只有当我记得它时 - 像今天这样的日子,当它再次获得赞成票时)所以我终于更新了它。我上面的原始答案仍然有效,但下面的更新答案更好。

任何批处理文件重命名操作一样,这应该使用perl rename实用程序来完成,而不是使用一些笨拙的 shell for 循环。

perl 重命名实用程序实际上是一种专门的脚本语言,它允许您使用任何 perl 代码来重命名文件,从简单的s/search/replace/正则表达式操作(足以满足大多数重命名任务)到复杂的多行脚本。

例如

rename -n 'BEGIN {use Date::Format};
           die $! unless -f $_;
           next if (m/-\d{8}$/);
           my $ts=(stat($_))[9];
           my $dt=time2str("%Y%m%d",$ts);
           s/$/-$dt/;' *.txt
Run Code Online (Sandbox Code Playgroud)

这只需要 perl 和Date::Format模块(一个非常有用的模块,它应该安装在任何带有 perl 的系统上。IMO 它与作者 Graham Barr 的Date::Parse模块一起应该是 perl 核心模块库的一部分,但事实并非如此您必须使用cpanDebian 软件包之类的发行版软件包安装它libtimedate-perl)。

顺便说一句,这个脚本会跳过任何看起来在文件名末尾已经有日期(即 8 位数字)的文件。

或者,对于将日期放在文件后缀(如果有)之前的更高级版本:

rename -n 'BEGIN {use Date::Format; use File::Basename};
           die $! unless -f $_;
           my ($filename,$dirs,$suffix) = fileparse($_,qr/\.[^.]*/);
           next if (m/-\d{8}${suffix}$/);
           my $ts=(stat($_))[9];
           my $dt=time2str("%Y%m%d",$ts);
           s/${suffix}$/-${dt}${suffix}/;' *.txt
Run Code Online (Sandbox Code Playgroud)

这个版本没有额外的要求,因为File::Basename只要我记得(至少十年,可能更长),该模块已经作为标准核心模块包含在 perl 中。

注意:rename上面的两个脚本都使用重命名的-n(又名--nono)“dry-run”选项,以便可以在应用之前测试/模拟结果。当您确定它可以满足您的要求时,删除-n(或将其替换-v为详细输出)。

另请注意:与任何其他 perlrename脚本一样,这可以重命名在命令行和/或标准输入中提供的文件名。例如重命名当前目录和所有子目录中的所有 .txt 文件:

find . -type f -iname '*.txt' -print0 | 
   rename -0 --nofullpath -n '..........'
Run Code Online (Sandbox Code Playgroud)

顺便说一句,我在这里使用了rename--nofullpath (又名-d, --filenmame, --nopath)选项来确保它只重命名找到的任何文件路径的文件名部分。在这种特殊情况下不需要它(因为示例重命名脚本只更改文件名的末尾)但通常是一个好主意,当您不想重命名路径和文件名时(例如重命名脚本喜欢's/ //g'删除文件名中的空格会尝试删除路径中的任何空格以及不带 的文件名--nofullpath,可能会导致它失败并出现错误)。

最后:不要将 perl 重命名脚本(也称为File::Rename,有时prename在 Fedora 和 RedHat 上调用,或perl-rename)与任何其他称为重命名的程序混淆。 只有这个基于 perl 的重命名实用程序可以使用任意 perl 代码重命名文件,如上所示,任何其他重命名实用程序将具有不同的功能和不同且不兼容的命令行选项。

您可以检查是否安装了正确的重命名:

$ rename -V
/usr/bin/rename using File::Rename version 1.13, File::Rename::Options version 1.10
Run Code Online (Sandbox Code Playgroud)

该可执行文件可能被称为prenameperl-rename或者file-rename您的系统上,所以尽量-V与那些和调整上面的例子使用了正确的可执行文件的名称。


jgo*_*afe 14

快速而肮脏的 Bash one-liner 将当前目录中的所有(全局)文件重命名filename.txtfilename.txt-20120620

for f in *; do mv -- "$f" "$f-$(stat -c %Y "$f" | date +%Y%m%d)"; done
Run Code Online (Sandbox Code Playgroud)

我敢肯定,一个有进取心的 Bash 书呆子会找到一些边缘情况来打破它。:)

显然,这不会做一些理想的事情,比如检查文件是否已经有一些看起来像日期的东西。

  • 那是什么样的`date`实现?我的 GNU `date` 似乎不能处理输入。 (5认同)
  • 好抓马纳特工作。我的 GNU 日期 8.13 也不支持从标准输入读取。它确实支持使用带有“-r”的文件的修改时间 - 例如“date +%Y%m%d -r $f”,因此在这种特殊情况下甚至不需要 stat 。 (5认同)
  • +1,看起来不错。您可以通过使用“--”作为 mv 的第一个 arg 使其更加健壮。防止以“-”开头的文件 (2认同)
  • @jgoldschrafe,您确定代码适合您吗?http://pastebin.com/nNYubf3A (2认同)