我正在尝试使用日期后缀:
批量重命名当前文件夹中的所有文件rename 's/(.*)/$1_$(date +%F)/' *
但该命令正在将info.txt
重命名为info.txt_1000 4 24 27 30 46 113 128 1000date +%F)
。我希望结果为info.txt_2016-10-13
答案 0 :(得分:3)
您希望$1
按字面意思传递给rename
,然后让$(date +%F)
由shell进行扩展。当你使用单引号时,后者不会发生,只有双引号。解决方案是使用双引号并转义$1
,以便shell不会扩展它。
rename "s/(.*)/\$1_$(date +%F)/" *
答案 1 :(得分:0)
既然你说“在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 … -print0
和xargs -0
来确保正确保留间距(而不是空格,这些使用空字符作为分隔符)。
您也可以使用perl rename
执行此操作:
find . -type f -not -name '*_20??-??-??' -print0 |xargs -0 \
rename "s/(.*)/\$1_$( date +%F )/"