通过减去值重命名文件名的末尾
rename the end of filename by subtracting value
我在 macOS 上的 ns_up/ 目录中有以下文件:
sqRatio_ist_LogSplineInterpPk_iz_260.dat
sqRatio_ist_LogSplineInterpPk_iz_261.dat
sqRatio_ist_LogSplineInterpPk_iz_262.dat
sqRatio_ist_LogSplineInterpPk_iz_263.dat
sqRatio_ist_LogSplineInterpPk_iz_264.dat
sqRatio_ist_LogSplineInterpPk_iz_265.dat
sqRatio_ist_LogSplineInterpPk_iz_266.dat
sqRatio_ist_LogSplineInterpPk_iz_267.dat
sqRatio_ist_LogSplineInterpPk_iz_268.dat
sqRatio_ist_LogSplineInterpPk_iz_269.dat
sqRatio_ist_LogSplineInterpPk_iz_270.dat
sqRatio_ist_LogSplineInterpPk_iz_271.dat
sqRatio_ist_LogSplineInterpPk_iz_272.dat
sqRatio_ist_LogSplineInterpPk_iz_273.dat
sqRatio_ist_LogSplineInterpPk_iz_274.dat
sqRatio_ist_LogSplineInterpPk_iz_275.dat
sqRatio_ist_LogSplineInterpPk_iz_276.dat
sqRatio_ist_LogSplineInterpPk_iz_277.dat
sqRatio_ist_LogSplineInterpPk_iz_278.dat
sqRatio_ist_LogSplineInterpPk_iz_279.dat
sqRatio_ist_LogSplineInterpPk_iz_280.dat
sqRatio_ist_LogSplineInterpPk_iz_281.dat
sqRatio_ist_LogSplineInterpPk_iz_282.dat
sqRatio_ist_LogSplineInterpPk_iz_283.dat
sqRatio_ist_LogSplineInterpPk_iz_284.dat
sqRatio_ist_LogSplineInterpPk_iz_285.dat
sqRatio_ist_LogSplineInterpPk_iz_286.dat
sqRatio_ist_LogSplineInterpPk_iz_287.dat
sqRatio_ist_LogSplineInterpPk_iz_288.dat
sqRatio_ist_LogSplineInterpPk_iz_289.dat
sqRatio_ist_LogSplineInterpPk_iz_290.dat
sqRatio_ist_LogSplineInterpPk_iz_291.dat
sqRatio_ist_LogSplineInterpPk_iz_292.dat
sqRatio_ist_LogSplineInterpPk_iz_293.dat
sqRatio_ist_LogSplineInterpPk_iz_294.dat
sqRatio_ist_LogSplineInterpPk_iz_295.dat
sqRatio_ist_LogSplineInterpPk_iz_296.dat
sqRatio_ist_LogSplineInterpPk_iz_297.dat
sqRatio_ist_LogSplineInterpPk_iz_298.dat
sqRatio_ist_LogSplineInterpPk_iz_299.dat
我想通过在文件名末尾减去值 200 来重命名每个文件,例如:
sqRatio_ist_LogSplineInterpPk_iz_299.dat = sqRatio_ist_LogSplineInterpPk_iz_99.dat
我尝试了以下操作:
for i in $(ls ns_up/); do
number=$(echo $i | gsed 's/\(.*\)_\(.*\).dat//')
new_number=$((number-200))
echo $i | gsed 's/_\(.*\)\.dat/"$new_number"\.dat/'
done
但不幸的是,这不起作用,我不知道为什么。
有人有想法吗?
您可以使用 homebrew 安装 (Perl) rename
使用:
brew install rename
然后尝试:
rename -n 's/(\d+)/ - 200/e' ns_up/*dat
-n
说要做 "dry run",即说它会做什么,但实际上没有做任何事情。
单引号中的 Perl 表达式,在变量 $_
中依次接收每个文件名,并期望修改它和 return 同一变量中的新值。
替换为 "substitute any bunch of adjacent digits it finds with that number minus 200."
e
表示评估替换的右侧。
这种方法有一些额外的好处:
- 你可以轻松干运行
- 如果任何两个输入文件名产生相同的输出文件名,它不会破坏文件
- 查看手册页了解更多优势
在 gnu sed 上试过:
find . -iregex '.+sqRatio_ist_LogSplineInterpPk_iz_2[0-9]+\.dat' -exec sh -c 'mv {} `echo {}|sed -E "s/(.+_)2([0-9]+\.dat)//"`' \;
你的命令的问题是你那里没有 mv
命令而且你没有计算新文件名的左边部分。这有效:
▶ for i in ns_up/* ; do
n=$(echo "$i" | gsed -E 's/(.*)_([0-9]+).dat//')
new_n=$((n - 200))
left=$(echo "$i" | gsed -E 's/[0-9]+.*//')
mv -i "$i" "$left${new_n}.dat"
done
备注:
我已指定 mv -i
以防止意外覆盖文件。
我在 sed 命令中使用了 -E
来使用扩展正则表达式,允许这里使用更简洁的语法。
我使用 gsed -E 's/(.*)_([0-9]+).dat//'
而不是你的 gsed 's/\(.*\)_\(.*\).dat//'
因为显式匹配 [0-9]+
(数字)更清楚,更明确你正在匹配哪个下划线。
这可能是您想要做的(使用 bash 进行 BASH_REMATCH[] 和 $((..)) 算术运算):
for old in ns_up/*.dat; do
[[ $old =~ ^(.*)_(.*)(\.dat)$ ]] || { printf 'Warning, unexpected old file name format "%s"\n' "$old" >&2; continue; }
new="${BASH_REMATCH[1]}$((${BASH_REMATCH[2]}-200))${BASH_REMATCH[3]}"
[[ -f "$new" ]] && { printf 'Warning, new file name "%s" generated from "%s" already exists, skipping.\n' "$new" "$old" >&2; continue; }
mv -- "$old" "$new"
done
您需要对现有的新文件进行测试,因为新文件名可能与现有文件名相同,您可能不想覆盖它。
这可能对你有用(GNU 并行):
parallel --dryrun mv {} '{= s/(\d+)/ - 200/e =}' ::: *.dat
检查生成的命令后,删除 --dryrun
选项。
我在 macOS 上的 ns_up/ 目录中有以下文件:
sqRatio_ist_LogSplineInterpPk_iz_260.dat
sqRatio_ist_LogSplineInterpPk_iz_261.dat
sqRatio_ist_LogSplineInterpPk_iz_262.dat
sqRatio_ist_LogSplineInterpPk_iz_263.dat
sqRatio_ist_LogSplineInterpPk_iz_264.dat
sqRatio_ist_LogSplineInterpPk_iz_265.dat
sqRatio_ist_LogSplineInterpPk_iz_266.dat
sqRatio_ist_LogSplineInterpPk_iz_267.dat
sqRatio_ist_LogSplineInterpPk_iz_268.dat
sqRatio_ist_LogSplineInterpPk_iz_269.dat
sqRatio_ist_LogSplineInterpPk_iz_270.dat
sqRatio_ist_LogSplineInterpPk_iz_271.dat
sqRatio_ist_LogSplineInterpPk_iz_272.dat
sqRatio_ist_LogSplineInterpPk_iz_273.dat
sqRatio_ist_LogSplineInterpPk_iz_274.dat
sqRatio_ist_LogSplineInterpPk_iz_275.dat
sqRatio_ist_LogSplineInterpPk_iz_276.dat
sqRatio_ist_LogSplineInterpPk_iz_277.dat
sqRatio_ist_LogSplineInterpPk_iz_278.dat
sqRatio_ist_LogSplineInterpPk_iz_279.dat
sqRatio_ist_LogSplineInterpPk_iz_280.dat
sqRatio_ist_LogSplineInterpPk_iz_281.dat
sqRatio_ist_LogSplineInterpPk_iz_282.dat
sqRatio_ist_LogSplineInterpPk_iz_283.dat
sqRatio_ist_LogSplineInterpPk_iz_284.dat
sqRatio_ist_LogSplineInterpPk_iz_285.dat
sqRatio_ist_LogSplineInterpPk_iz_286.dat
sqRatio_ist_LogSplineInterpPk_iz_287.dat
sqRatio_ist_LogSplineInterpPk_iz_288.dat
sqRatio_ist_LogSplineInterpPk_iz_289.dat
sqRatio_ist_LogSplineInterpPk_iz_290.dat
sqRatio_ist_LogSplineInterpPk_iz_291.dat
sqRatio_ist_LogSplineInterpPk_iz_292.dat
sqRatio_ist_LogSplineInterpPk_iz_293.dat
sqRatio_ist_LogSplineInterpPk_iz_294.dat
sqRatio_ist_LogSplineInterpPk_iz_295.dat
sqRatio_ist_LogSplineInterpPk_iz_296.dat
sqRatio_ist_LogSplineInterpPk_iz_297.dat
sqRatio_ist_LogSplineInterpPk_iz_298.dat
sqRatio_ist_LogSplineInterpPk_iz_299.dat
我想通过在文件名末尾减去值 200 来重命名每个文件,例如:
sqRatio_ist_LogSplineInterpPk_iz_299.dat = sqRatio_ist_LogSplineInterpPk_iz_99.dat
我尝试了以下操作:
for i in $(ls ns_up/); do
number=$(echo $i | gsed 's/\(.*\)_\(.*\).dat//')
new_number=$((number-200))
echo $i | gsed 's/_\(.*\)\.dat/"$new_number"\.dat/'
done
但不幸的是,这不起作用,我不知道为什么。
有人有想法吗?
您可以使用 homebrew 安装 (Perl) rename
使用:
brew install rename
然后尝试:
rename -n 's/(\d+)/ - 200/e' ns_up/*dat
-n
说要做 "dry run",即说它会做什么,但实际上没有做任何事情。
单引号中的 Perl 表达式,在变量 $_
中依次接收每个文件名,并期望修改它和 return 同一变量中的新值。
替换为 "substitute any bunch of adjacent digits it finds with that number minus 200."
e
表示评估替换的右侧。
这种方法有一些额外的好处:
- 你可以轻松干运行
- 如果任何两个输入文件名产生相同的输出文件名,它不会破坏文件
- 查看手册页了解更多优势
在 gnu sed 上试过:
find . -iregex '.+sqRatio_ist_LogSplineInterpPk_iz_2[0-9]+\.dat' -exec sh -c 'mv {} `echo {}|sed -E "s/(.+_)2([0-9]+\.dat)//"`' \;
你的命令的问题是你那里没有 mv
命令而且你没有计算新文件名的左边部分。这有效:
▶ for i in ns_up/* ; do
n=$(echo "$i" | gsed -E 's/(.*)_([0-9]+).dat//')
new_n=$((n - 200))
left=$(echo "$i" | gsed -E 's/[0-9]+.*//')
mv -i "$i" "$left${new_n}.dat"
done
备注:
我已指定
mv -i
以防止意外覆盖文件。我在 sed 命令中使用了
-E
来使用扩展正则表达式,允许这里使用更简洁的语法。我使用
gsed -E 's/(.*)_([0-9]+).dat//'
而不是你的gsed 's/\(.*\)_\(.*\).dat//'
因为显式匹配[0-9]+
(数字)更清楚,更明确你正在匹配哪个下划线。
这可能是您想要做的(使用 bash 进行 BASH_REMATCH[] 和 $((..)) 算术运算):
for old in ns_up/*.dat; do
[[ $old =~ ^(.*)_(.*)(\.dat)$ ]] || { printf 'Warning, unexpected old file name format "%s"\n' "$old" >&2; continue; }
new="${BASH_REMATCH[1]}$((${BASH_REMATCH[2]}-200))${BASH_REMATCH[3]}"
[[ -f "$new" ]] && { printf 'Warning, new file name "%s" generated from "%s" already exists, skipping.\n' "$new" "$old" >&2; continue; }
mv -- "$old" "$new"
done
您需要对现有的新文件进行测试,因为新文件名可能与现有文件名相同,您可能不想覆盖它。
这可能对你有用(GNU 并行):
parallel --dryrun mv {} '{= s/(\d+)/ - 200/e =}' ::: *.dat
检查生成的命令后,删除 --dryrun
选项。