0

我有很多文件被命名为:MM-DD-YYYY.pdf. 我想重命名它们,因为YYYY-MM-DD.pdf 我确信有一些 bash 魔法可以做到这一点。它是什么?

4

4 回答 4

4

对于当前目录中的文件:

for name in ./??-??-????.pdf; do
    if [[ "$name" =~ (.*)/([0-9]{2})-([0-9]{2})-([0-9]{4})\.pdf ]]; then
        echo mv "$name" "${BASH_REMATCH[1]}/${BASH_REMATCH[4]}-${BASH_REMATCH[3]}-${BASH_REMATCH[2]}.pdf"
    fi
done

递归地,在当前目录中或下:

find . -type f -name '??-??-????.pdf' -exec bash -c '
    for name do
        if [[ "$name" =~ (.*)/([0-9]{2})-([0-9]{2})-([0-9]{4})\.pdf ]]; then
            echo mv "$name" "${BASH_REMATCH[1]}/${BASH_REMATCH[4]}-${BASH_REMATCH[3]}-${BASH_REMATCH[2]}.pdf"
        fi
    done' bash {} +

启用globstarshell 选项bash可以让我们执行以下操作(也将像上面的解决方案一样,处理当前目录中或之下的所有文件):

shopt -s globstar

for name in **/??-??-????.pdf; do
    if [[ "$name" =~ (.*)/([0-9]{2})-([0-9]{2})-([0-9]{4})\.pdf ]]; then
        echo mv "$name" "${BASH_REMATCH[1]}/${BASH_REMATCH[4]}-${BASH_REMATCH[3]}-${BASH_REMATCH[2]}.pdf"
    fi
done

所有这三个解决方案都使用正则表达式来挑选文件名的相关部分,然后将这些部分重新排列为新名称。它们之间的唯一区别是如何生成路径名列表。

代码前缀mvecho安全起见。要实际重命名文件,请删除echo(但至少运行一次 echo查看它是否符合您的要求)。

于 2018-05-10T12:07:31.437 回答
1

命令行中的直接方法示例:

$ ls
10-01-2018.pdf  11-01-2018.pdf  12-01-2018.pdf
$ ls [0-9]*-[0-9]*-[0-9]*.pdf|sed -r 'p;s/([0-9]{2})-([0-9]{2})-([0-9]{4})/\3-\1-\2/'|xargs -n2 mv
$ ls
2018-10-01.pdf  2018-11-01.pdf  2018-12-01.pdf

ls输出通过管道传送到,sed然后我们使用p标志不加修改地打印参数,换句话说,文件的原始名称,并使用s执行并输出转换。

ls+ sed结果是由一系列old_file_namenew_file_name组成的组合输出。

最后,我们通过管道传递结果xargs以获取文件的有效重命名。

来自xargs 男人

-n number 使用尽可能多的标准输入参数执行命令,最大参数数量。

于 2018-05-10T09:10:55.103 回答
0

您可以使用非常接近klashxx之一的以下命令:

for f in *.pdf; do echo "$f"; mv "$f" "$(echo "$f" | sed 's@\(..\)-\(..\)-\(....\)@\3-\2-\1@')"; done

前:

ls *.pdf
12-01-1998.pdf  12-03-2018.pdf

后:

ls *.pdf
1998-01-12.pdf  2018-03-12.pdf

此外,如果您的文件夹中有其他pdf不符合此格式的文件,您可以做的是仅选择符合该格式的文件:MM-DD-YYYY.pdf为此,请使用以下命令:

for f in `find . -maxdepth 1 -type f -regextype sed -regex './[0-9]\{2\}-[0-9]\{2\}-[0-9]\{4\}.pdf' | xargs -n1 basename`; do echo "$f"; mv "$f" "$(echo "$f" | sed 's@\(..\)-\(..\)-\(....\)@\3-\2-\1@')"; done

说明:

  • find . -maxdepth 1 -type f -regextype sed -regex './[0-9]\{2\}-[0-9]\{2\}-[0-9]\{4\}.pdf此 find 命令将仅在当前工作目录中查找符合您的语法并提取其基本名称的文件(删除./开头的,文件夹和其他类型的文件将不考虑同名文件,其他*.pdf文件也是忽略。

  • for each file您移动并使用 sed 计算生成的文件名,并反向引用 MM、DD 和 YYYY 的 3 个组

于 2018-05-10T09:15:40.147 回答
0

对于这些简单的文件名,使用更详细的模式,您可以稍微简化循环体:

twodigit=[[:digit:]][[:digit:]]
fourdigit="$twodigit$twodigit"
for f in $twodigit-$twodigit-$fourdigit.pdf; do
  IFS=- read month day year <<< "${f%.pdf}"
  mv "$f" "$year-$month-$day.pdf"
done

这基本上是@Kusalananda 的答案,但没有正则表达式匹配的冗长。

于 2018-05-10T12:40:58.767 回答