我的文件看起来像这样:
ABC_20210101.csv
ABC_20210101_imp.csv
我想将文件名中的日期更新为特定日期:
ABC_20201231.csv
ABC_20201231_imp.csv
我该如何替换这些文件名?
答案1
使用 GNU 并行:
ls | parallel mv {} '{= s/(.*)\d{8}/${1}20210131/ =}'
测试于:
this_123456789_file_19991231_some.thing
如果您无权在将要运行的系统上安装软件,您可以将 GNU Parallel 直接包含在脚本中:
parallel --embed > newscript.sh
答案2
您bash
可以将文件名分开并重新组合
#!/bin/bash
new="20201231"
for file in *.csv
do
# Split the filename into its consituent parts
if [[ "$a" =~ (.*)[0-9]{8}(_imp)?(\.csv)$ ]]
then
# Assemble a new filename
dest="${BASH_REMATCH[1]}${new}${BASH_REMATCH[2]}${BASH_REMATCH[3]}"
if [[ ! -f "$dest" ]]
then
# No destination so rename
[[ -t 2 ]] && echo "Rename $file as $dest" >&2
echo mv -f "$file" "$dest" # Remove "echo" to action
fi
fi
done
这更容易,rename
但并非所有系统都安装了它(删除-n
或替换-v
为操作):
new="20201231" rename -n 's/(.*)?[0-9]{8}(_imp)?(\.csv)$/$1$ENV{new}$2$3/' *.csv
如果没有bash
或者rename
则sed
可以用来生成必要的目标文件名。可以说,这是更容易阅读的代码(除了 RE,它有许多反斜杠转义以满足 的sed
ERE 处理)
new="20201231"
for file in *.csv
do
# Generate new filename
dest=$(
printf "%s\n" "$file" |
sed -n 's/\(.*\)[0-9]\{8\}\(_imp\)\{0,1\}\(\.csv\)$/\1---\2\3/p'
)
if [ -n "$dest" ] && [ ! -f "$dest" ]
then
# Pattern substitued and target does not exist so rename
[[ -t 2 ]] && echo "Rename $file as $dest" >&2
echo mv -f "$file" "$dest" # Remove "echo" to action
fi
done
答案3
重命名文件的一种方法是首先使用 find 实用程序 abd 选择文件,然后将它们传递给 sed,它将构造新名称,然后 tgen 将一对传递给 xargs 以调用 mv 命令来进行重命名。
d0=19710110
d8=$(seq -f '[0-9%g]' 8 | paste -sd'\0')
find . -maxdepth 1 -type f \( -name "*_${d8}_imp.csv" -o -name "*_$d8.csv" \) -print |
sed -Ee "h;/_[0-9]{8}((_imp)?[.]csv)\$/s//_$d0\1/;x;G" |
xargs -r -d'\n' -n2 -t mv -i
答案4
标准 POSIX sh
shell 允许我们编写如下模式
./*[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].csv
和
./*[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]_imp.csv
这些将与当前目录中您感兴趣的文件相匹配。 (显然,您可以使这些更具体,例如./*20[0-2][0-9][01][0-9][0-3][0-9].csv
,这仍然允许匹配无效日期。)然后可以像这样重命名匹配这些模式的名称:
for name in ./*[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].csv
do
[ ! -e "$name" ] && continue
newname=${name%[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].csv}20201231.csv
mv "$name" "$newname"
done
for name in ./*[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]_imp.csv
do
[ ! -e "$name" ] && continue
newname=${name%[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]_imp.csv}20201231_imp.csv
mv "$name" "$newname"
done
替换会从值的末尾${variable%pattern}
删除匹配的字符串。pattern
$variable