如何通过移动/替换字符并在文件名中转换日期格式来重命名bash中的多个文件?

时间:2018-12-22 03:33:52

标签: bash rename

在我的日志目录中,我有600多个日志文件,其命名方案为:

abc.log.DDMMMYYYY

例如:

abc.log.01Nov2017
abc.log.02Nov2017
abc.log.10Dec2017
abc.log.21Jan2018
abc.log.22Jan2018
abc.log.23Jan2018

我正在寻找一种将所有这些文件重命名为...的方法

YYYY-MM-DD.abc.log

文件名中的月份名称必须转换为月份号。 (一月= 01,二月= 02 ...)

例如:

2017-11-01.abc.log
2017-11-02.abc.log
2017-12-10.abc.log
2018-01-21.abc.log
2018-01-22.abc.log
2018-01-23.abc.log

如何在bash中重命名所有这些文件?

3 个答案:

答案 0 :(得分:2)

#!/bin/bash -e

# Create kludged associative array (for bash versions prior to 4 -- 4 has
# built-in associative arrays).
i=0
for Month in Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec; do
    let i=i+1
    # Pad with leading zero and then take last two characters.
    Padded=0$i
    eval Key$Month=${Padded: -2:2}
done

# Iterate on all files whose names match *.log.*.
for File in *.log.*; do
    # Match to pattern with expected date format.
    if [[ ! $File =~ ^(.*)\.log\.([0-3][0-9])([A-Z][a-z][a-z])([0-9]{4})$ ]]; then
        echo "$File does not match pattern."
    else
        # Extract matched name and date.
        Name=${BASH_REMATCH[1]}
        Day=${BASH_REMATCH[2]}
        InMonth=${BASH_REMATCH[3]}
        Year=${BASH_REMATCH[4]}

        # Convert month name abbreviation to month number.
        # number %m, day number %d).
        eval OutMonth=\$Key$InMonth
        NewName="$Year-$OutMonth-$Day.$Name.log"

        # Inform user.
        echo "Will rename $File to $NewName."

        # Rename.
        mv "$File" "$NewName"
    fi
done

当然,这是对语言环境敏感的。而且它期望四位数的日期,所以它将在10,000年终止。您可以添加各种错误检查。

答案 1 :(得分:1)

当您请求批处理文件解决方案时,以下是可能的解决方案:

@echo off
setlocal EnableDelayedExpansion

rem Set Month Numbers:
set "Jan=01"
set "Feb=02"
set "Mar=03"
set "Apr=04"
set "May=05"
set "Jun=06"
set "Jul=07"
set "Aug=08"
set "Sep=09"
set "Oct=10"
set "Nov=11"
set "Dec=12"

rem Main Loop to rename files:
for %%A IN (*.log.*) do (
     for /f "delims=." %%B IN ("%%~xA") do (
          set "extension=%%B"
          call ren "%%A" "!extension:~5!-%%!extension:~2,-4!%%-!extension:~0,-7!.abc.log"
     )
)

让我解释一下:

  • 首先,我们将MMM变量设置为请求的格式:MM
  • 现在,我们进入主循环。
    • 我们遍历当前文件夹(%cd%)中包含.log.的所有文件。我们使用*通配符进行此操作。
      • 然后,我们循环找到的每个文件的扩展名。
        • 我们在变量.中设置扩展名(不带点(extension)。
        • 然后,我们使用找到并分析的字符串重命名在第一个循环(%%A)中找到的文件。

为了更好地理解这些命令的工作方式,建议您打开一个cmd并键入以下命令:

  • set /?
  • rem /?
  • for /?
  • ren /?

一些有趣的参考资料供进一步阅读:

答案 2 :(得分:0)

如果gawk可用,请尝试:

#!/bin/bash

for f in abc.log.*; do echo "$f"; done | awk 'BEGIN {
    str="JanFebMarAprMayJunJulAugSepOctNovDec"
    for (i=1; i<=12; i++) s2n[substr(str, i*3-2, 3)] = sprintf("%02d", i)
    }
    {if (match($0, "(.+)\\.([0-9]{2})([A-Z][a-z]{2})([0-9]{4})", a))
    printf("%s%c%04d-%02d-%02d.%s%c", $0, 0, a[4], s2n[a[3]], a[2], a[1], 0)
    }
' | xargs -0 -n 2 mv
  • 它通过数组s2n将月份名称映射到月份号。
  • awk脚本输出成对的文件名,例如:abc.log.01Nov20172017-11-01.abc.log ...文件名用空字符分隔。
  • xargs逐两读取传递的文件名,并在 他们。