在Unix中批量重命名文件,当前日期为后缀

时间:2016-10-13 22:25:01

标签: linux bash unix batch-rename

我正在尝试使用日期后缀:

批量重命名当前文件夹中的所有文件
rename 's/(.*)/$1_$(date +%F)/' *

但该命令正在将info.txt重命名为info.txt_1000 4 24 27 30 46 113 128 1000date +%F)。我希望结果为info.txt_2016-10-13

2 个答案:

答案 0 :(得分:3)

您希望$1按字面意思传递给rename,然后让$(date +%F)由shell进行扩展。当你使用单引号时,后者不会发生,只有双引号。解决方案是使用双引号并转义$1,以便shell不会扩展它。

rename "s/(.*)/\$1_$(date +%F)/" *

答案 1 :(得分:0)

便携式Posix shell解决方案

既然你说“在Unix中”并且rename命令不可移植(它实际上是perl包的一部分),这里的解决方案应该适用于更多环境:

for file in *; do mv "$file" "${file}_$( date +%F )"; done

这会创建一个循环,然后将每个单独的文件移动到新名称。与问题一样,它使用date +%F通过shell进程替换来插入“完整日期”(YYYY-mm-dd)。进程替换必须使用双引号(")而不是单引号('),因为单引号会关闭shell解释(这也适用于变量),如John's answer中所述。< / p>

参数列表太长

如果目录中包含太多文件,您的shell会抱怨,并出现“参数列表太长”等错误。这是因为*扩展到目录的内容,所有这些都成为您正在运行的命令的参数。

要解决这个问题,请创建一个脚本,然后通过xargs提供,如下所示:

#!/bin/sh
if [ -z "$1" ]; then set *; fi  # default to all files in curent directory
for file in "$@"; do mv "$file" "${file}_$( date +%F )"; done

使用ls生成文件列表对于脚本来说并不总是明智的(在某些情况下它可以做奇怪的事情)。请改用find

find . -type f -not -name '*_20??-??-??' -print0 |xargs -0 sh /path/to/script.sh

注意,该命令是递归的(通过在点之后添加-maxdepth 1来改变它)。 find非常有能力。在此示例中,它查找与shell glob -type f*_20??-??-??不匹配的所有文件(*)匹配任意数量的任何字符,?匹配恰好是任何一个字符中的一个,因此匹配abc_2016-10-14但不匹配abc_2016-10-14-def)。这使用find … -print0xargs -0来确保正确保留间距(而不是空格,这些使用空字符作为分隔符)。

您也可以使用perl rename执行此操作:

find . -type f -not -name '*_20??-??-??' -print0 |xargs -0 \
  rename "s/(.*)/\$1_$( date +%F )/"
相关问题