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

问题描述 投票:1回答:5

我在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

但不幸的是,这不起作用,我不知道为什么。

任何人都有想法?

macos sed file-rename
5个回答
3
投票

你可以用homebrew安装(Perl)rename

brew install rename

然后尝试:

rename -n 's/(\d+)/$1 - 200/e' ns_up/*dat

-n说要做一个“干跑”,即说它会做什么,而不是实际做任何事情。

单引号中的Perl表达式在变量$_中依次接收每个文件名,并且应该修改它并在同一变量中返回新值。

替换说“用这个数字减去200替换它找到的任何相邻数字串。”

e说要评估替换的右侧。

这种方法有一些额外的好处:

  • 你可以轻松地做一个干运行
  • 如果任何两个输入文件名导致相同的输出文件名,它将不会破坏文件
  • 有关更多优点,请参阅手册页

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

您需要对现有的新测试进行测试,因为新文件名可能与现有文件名相同,您可能不想覆盖它。


1
投票

这可能对你有用(GNU并行):

parallel --dryrun mv {} '{= s/\d+/& - 200/e =}' ::: *.dat

检查生成的命令后,删除--dryrun选项。


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/"`' \;

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以防止意外覆盖文件。
  • 我已经使用-E来使用sed命令来使用扩展正则表达式,这里允许更清晰的语法。
  • 我使用gsed -E 's/(.*)_([0-9]+).dat/\2/'而不是你的gsed 's/\(.*\)_\(.*\).dat/\2/',因为明确地匹配[0-9]+(数字)更明确,更清楚你匹配哪个下划线。
© www.soinside.com 2019 - 2024. All rights reserved.