通过减去值来重命名文件名的末尾

时间:2019-04-28 08:10:20

标签: macos sed file-rename

在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

但是不幸的是,这行不通,我也不知道为什么。

任何人都会有个主意吗?

5 个答案:

答案 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]+(数字)更清晰,也更明确地确定了您要匹配的下划线。

    < / li>