在我的用例中是否有一种纯粹的 bash 方法来消除一些外部命令?

Is there a pure bash way to eliminate some external commands in my use case?

我是 运行 OS X 10.8.5 所以 rename 命令不是一个选项,我编写的代码与 bash 脚本正在这样做,我宁愿留在这个框架内,但如果可能的话,稍微修改一下。但是,我使用的是 bash 的更高版本,然后是 OS X 10.8.5 发货默认值,我使用的是 GNU bash 4.3.30,我从源代码安装的。 (是的,我知道我落后了几个补丁。

我想在下面的函数中做的,如果可能的话,是替换mv的命令target 参数使用 命令替换 完全 纯 bash。更具体地说,我想消除对 pipesexternal executables.

的使用

问题:我正在使用的命令替换是否可以修改或替换为文件名扩展 和/或 模式匹配 不使用 管道 外部可执行文件 来实现我的既定目标? (或者其他更合理的。)

示例文件名: filenameC01P01.png filenameC01P02foobar.jpg filenameC01P03.tif

预期输出: filenameC01P02foobar.jpg -> filenameC01P02.jpg

代码:

function truncate_filenames () {
  for f in *.png *.jpg *.tif; do
      if [[ -f $f ]]; then
          ext="${f:(-3)}"
          if [[ ! ${f%.*} =~ .*C[0-9]{2}P[0-9]{2}$ ]]; then
              mv -v "$f" "$(echo "$f" | grep -Eo '.*C[0-9]{2}P[0-9]{2}').$ext"
          fi
      fi
  done
}

您似乎只想删除 CxxPxx 模板之后的所有内容,但保留扩展名。

# Capture both the good part and the trailing garbage
[[ ${f%.*} =~ (.*C[0-9]{2}P[0-9]{2})(.*)$ ]]
if [[ -n ${BASH_REMATCH[2]} ]]; then
    mv -v "$f" "${BASH_REMATCH[1]}.$ext"
fi

您也可以在正则表达式中捕获扩展名,无需单独提取它。

[[ $f =~ (.*C[0-9]{2}P[0-9]{2})(.*)\.(.*)$ ]]
if [[ -n ${BASH_REMATCH[2]} ]]; then
    mv -v "$f" "${BASH_REMATCH[1]}.${BASH_REMATCH[3]}"
fi