在awk中使用多个字段分隔符重命名多个文件

Renaming multiple files with multiple field separator in awk

我需要将以下文件同样从 PFSI4C.CSC.CCC.FSIContractData20211008.zip 重命名为 TFSI4C.CSC.CCC.FSIContractData20211104.zip.

每个文件的名称都应以“T”开头并以当前系统日期 + .zip 结尾

我正在尝试遍历文件,它看起来像这样:

for FILENAME in PFSI4C.CSC.CCC.FSIContractData20211008; do
    NEW_FILENAME_HEADER=`echo $FILENAME | awk -F "." '{ print ".""." }'` # which would takes PFSI4C.CSC.CCC.
    NEW_FILENAME_SUFFIX=`echo $FILENAME | awk -F "[.|Data20]" '{ print "." }'` # this part where I can't figure out to take only "FSIContract"
    NEW_FILENAME="${NEW_FILENAME_HEADER}.""${NEW_FILENAME_SUFFIX}""Data20""${DATE}".zip" # which should make "TFSI4C.CSC.CCC.FSIContractData20211104.zip."
    mv $FILENAME $NEW_FILENAME
  done
  

仅供参考 $DATE 在我们的脚本中定义如下:DATE='date +'%y%m%d' 例如 211104

提前致谢!

首先,您应该使用 date +%Y%m%d(4 位数年份)而不是 date +%y%m%d(2 位数年份)获取当前日期。以下假设您这样做。如果不是一个选项,请将 20 添加到 $DATE

如果您的文件名都像您显示的示例 bash 替换即可。首先计算长度,提取日期前倒数第二个字符,前置T,追加$DATE.zip:

len="${#FILENAME}"
NEW_FILENAME="T${FILENAME:1:$((len-13))}$DATE.zip"

但您也可以使用 sed,它提供了更多的灵活性。例如,它可以处理可变位数的结束日期:

NEW_FILENAME=$(echo "$FILENAME" | sed 's/.\(.*[^0-9]\)\?[0-9]*\.zip/T'"$DATE"'.zip/')

或者,使用 bash(此处为字符串)和 GNU sed 或其他支持 -E 选项(用于扩展正则表达式)的 sed 更优雅:

NEW_FILENAME=$(sed -E 's/.(.*[^0-9])?[0-9]*\.zip/T'"$DATE"'.zip/' <<< "$FILENAME")

假设:

  • T
  • 替换第一个字符(OP示例中的P
  • $DATE.zip替换最后10个字符(YYMMDD.zip)(OP已经定义$DATE
  • 所有文件都包含 20YYMMDD,因此我们无需担心名称包含 19YYMMDD21YYMMDD
  • 等字符串

使用 parameter substitutions 的一个想法(这也消除了执行各种 echoawksed 命令的子进程调用的开销):

DATE='211104'
FILENAME='PFSI4C.CSC.CCC.FSIContractData20211008.zip'

NEWFILENAME="T${FILENAME/?}"                           # prepend "T"; "/?" => remove first character
NEWFILENAME="${NEWFILENAME/??????.zip}${DATE}.zip"     # remove string "??????.zip"; append "${DATE}.zip"

echo mv "${FILENAME}" "${NEWFILENAME}"

这会生成:

mv PFSI4C.CSC.CCC.FSIContractData20211008.zip TFSI4C.CSC.CCC.FSIContractData20211104.zip

一旦 OP 对代码的准确性感到满意,就可以删除 echo 以启用 mv 命令的执行。

使用 Perl 的 rename 命令,您可以尝试使用以下代码。我在这里使用 -n 选项在 DRY 运行 模式下测试它,它只会打印文件名,从文件名(当前)到文件名(必需的)将被更改;一旦您对显示的输出感到满意,请删除代码中的 -n 。另外 DATE 变量 (DATE='20211104') 是一个 shell 变量,它包含新文件名中需要的日期值。

rename -n 's:^.(.*)\d{8}(\.zip)$:T:; s:\.zip$:'"$DATE"'.zip:' *.zip

输出如下:

rename(PFSI4C.CSC.CCC.FSIContractData20211008.zip, TFSI4C.CSC.CCC.FSIContractData20211104.zip)

rename代码解释:

  • -n: 运行 rename 命令处于 DRY 运行 模式。
  • s:^.(.*)\d{8}(\.zip)$:T:;:运行 rename 代码中的第一组替换。它创建 2 个捕获组,第一个捕获组包含从第二个字符开始到 8 位数字之前的所有内容,第二个捕获组在文件名末尾包含 .zip。根据要求将其替换为 T1
  • s:\.zip$:'"$DATE"'.zip::运行 rename 代码中的第二组替换。其中 .zip$ 带有 shell 变量 DATE 以及根据要求的 .zip。