在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/\2/')
new_number=$((number-200))
echo $i | gsed 's/_\(.*\)\.dat/"\$new_number"\.dat/'
done
但是不幸的是,这行不通,我也不知道为什么。
任何人都会有个主意吗?
答案 0 :(得分:3)
您可以使用以下方式通过自制软件安装(Perl)rename
:
brew install rename
然后尝试:
rename -n 's/(\d+)/$1 - 200/e' ns_up/*dat
-n
表示要进行“空运行” ,即说它会做什么,而实际上没有做任何事情。
Perl表达式用单引号引起来,依次在变量$_
中接收每个文件名,并期望对其进行修改并在同一变量中返回新值。
该替换表示“用找到的数字减去200替换成一串相邻的数字。”
e
说要评估替换的右侧。
这种方法还具有其他优点:
答案 1 :(得分:1)
这可能是您要尝试执行的操作(将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
您需要对已经存在的新文件进行测试,因为新文件名可能与现有文件名相同,并且您可能不想覆盖它。
答案 2 :(得分:1)
这可能对您有用(GNU并行):
parallel --dryrun mv {} '{= s/\d+/& - 200/e =}' ::: *.dat
检查生成的命令后,删除--dryrun
选项。
答案 3 :(得分:0)
尝试使用gnu sed:
find . -iregex '.+sqRatio_ist_LogSplineInterpPk_iz_2[0-9]+\.dat' -exec sh -c 'mv {} `echo {}|sed -E "s/(.+_)2([0-9]+\.dat)/\1\2/"`' \;
答案 4 :(得分:0)
命令的问题是您那里没有mv
命令,并且没有计算新文件名的左部分。这有效:
▶ for i in ns_up/* ; do
n=$(echo "$i" | gsed -E 's/(.*)_([0-9]+).dat/\2/')
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/\2/'
而不是您的gsed 's/\(.*\)_\(.*\).dat/\2/'
是因为明确匹配[0-9]+
(数字)更清晰,也更明确地确定了您要匹配的下划线。