在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
,因此我们无需担心名称包含 19YYMMDD
和 21YYMMDD
等字符串
使用 parameter substitutions 的一个想法(这也消除了执行各种 echo
、awk
和 sed
命令的子进程调用的开销):
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。
我需要将以下文件同样从 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示例中的 - 用
$DATE.zip
替换最后10个字符(YYMMDD.zip
)(OP已经定义$DATE
) - 所有文件都包含
20YYMMDD
,因此我们无需担心名称包含19YYMMDD
和21YYMMDD
等字符串
P
)
使用 parameter substitutions 的一个想法(这也消除了执行各种 echo
、awk
和 sed
命令的子进程调用的开销):
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。