如何使用bash字符串格式来反转日期格式?

如何使用bash字符串格式来反转日期格式?,bash,date-manipulation,Bash,Date Manipulation,我有很多文件名为:MM-DD-YYYY.pdf。我想将它们重命名为YYYY-MM-DD.pdf我确信有一些bash魔法可以做到这一点。这是什么?命令行中的直接进近示例: $ 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-0

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

命令行中的直接进近示例:

$ 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
结果是一个组合输出,由一系列旧文件名和新文件名组成

最后,我们通过管道将结果提要传递到
xargs
,以获得文件的有效重命名

xargs
man

-n使用尽可能多的标准输入参数对执行命令进行编号,最多使用数字参数


命令行中的直接进近示例:

$ 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
结果是一个组合输出,由一系列旧文件名和新文件名组成

最后,我们通过管道将结果提要传递到
xargs
,以获得文件的有效重命名

xargs
man

-n使用尽可能多的标准输入参数对执行命令进行编号,最多使用数字参数


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

之前:

ls *.pdf
12-01-1998.pdf  12-03-2018.pdf
ls *.pdf
1998-01-12.pdf  2018-03-12.pdf
之后:

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
    文件也将被忽略

  • 对于每个文件
    执行一次移动,并使用sed和对MM、DD和YYYY三个组的反向引用来计算结果文件名


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

之前:

ls *.pdf
12-01-1998.pdf  12-03-2018.pdf
ls *.pdf
1998-01-12.pdf  2018-03-12.pdf
之后:

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
    文件也将被忽略

  • 对于每个文件
    执行一次移动,并使用sed和对MM、DD和YYYY三个组的反向引用来计算结果文件名


对于当前目录中的文件:

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 {} +
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
递归地,在当前目录中或当前目录下:

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 {} +
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
bash
中启用
globstar
shell选项,我们可以执行以下操作(与上述解决方案一样,还可以处理当前目录中或以下的所有文件):

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


代码以
echo
作为
mv
的前缀,以确保安全。若要实际重命名文件,请删除
echo
(但使用
echo
至少运行一次,以查看它是否执行了所需操作)。

对于当前目录中的文件:

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 {} +
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
递归地,在当前目录中或当前目录下:

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 {} +
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
bash
中启用
globstar
shell选项,我们可以执行以下操作(与上述解决方案一样,还可以处理当前目录中或以下的所有文件):

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


代码以
echo
作为
mv
的前缀,以确保安全。要真正重命名文件,请删除
echo
(但使用
echo
至少运行一次,以查看它是否符合您的要求)。

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

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
two-digit=[:digit:][[:digit:][]
fourdigit=“$twodigit$twodigit”
对于f,在$two-digit-$two-digit-$fourdigit.pdf中;do

如果s=-read month day year对于这些简单的文件名,使用更详细的模式,可以稍微简化循环体:

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
two-digit=[:digit:][[:digit:][]
fourdigit=“$twodigit$twodigit”
对于f,在$two-digit-$two-digit-$fourdigit.pdf中;do

IFS=-阅读月-日-年你自己尝试了什么?我们可以帮助你的努力,而不是提供一个完整的答案solution@jlconlin:祝您飞行安全,抵达后请查看我们的答案!-)您为自己做了哪些尝试?我们可以帮助您的努力,而不是提供完整的解决方案