在我的用例中是否有一种纯粹的 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。更具体地说,我想消除对 pipes 和 external executables.
的使用
问题:我正在使用的命令替换是否可以修改或替换为文件名扩展 和/或 模式匹配 不使用 管道 或 外部可执行文件 来实现我的既定目标? (或者其他更合理的。)
我已经阅读了 Bash 参考手册中的三个相关部分,但是我不得不承认我并没有很容易地看到它是如何可能的。虽然我确实尝试重新编码了几次,但输出根本不是我想要的,它要么被损坏 filenames 要么错误 ... bad substitution
.
工作目录中的所有目标文件名要么已经匹配RegEx.$ext
,要么将RegEx+foobar.$ext
以及我对 函数 进行编码并使用 mv
的方式是,如果它尚未与 RegEx
匹配,它会重命名目标 filenames 从 RegEx+foobar.$ext
到 RegEx.$ext
。所有 文件名 被截断后 将是唯一的 ,因此无需担心覆盖现有 RegEx.$ext
文件名 因此不需要额外的 错误检查 。
示例文件名: 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
我是 运行 OS X 10.8.5 所以 rename
命令不是一个选项,我编写的代码与 bash 脚本正在这样做,我宁愿留在这个框架内,但如果可能的话,稍微修改一下。但是,我使用的是 bash 的更高版本,然后是 OS X 10.8.5 发货默认值,我使用的是 GNU bash 4.3.30,我从源代码安装的。 (是的,我知道我落后了几个补丁。)
我想在下面的函数中做的,如果可能的话,是替换mv
的命令target 参数使用 命令替换 完全 纯 bash。更具体地说,我想消除对 pipes 和 external executables.
问题:我正在使用的命令替换是否可以修改或替换为文件名扩展 和/或 模式匹配 不使用 管道 或 外部可执行文件 来实现我的既定目标? (或者其他更合理的。)
我已经阅读了 Bash 参考手册中的三个相关部分,但是我不得不承认我并没有很容易地看到它是如何可能的。虽然我确实尝试重新编码了几次,但输出根本不是我想要的,它要么被损坏 filenames 要么错误
... bad substitution
.工作目录中的所有目标文件名要么已经匹配
RegEx.$ext
,要么将RegEx+foobar.$ext
以及我对 函数 进行编码并使用mv
的方式是,如果它尚未与RegEx
匹配,它会重命名目标 filenames 从RegEx+foobar.$ext
到RegEx.$ext
。所有 文件名 被截断后 将是唯一的 ,因此无需担心覆盖现有RegEx.$ext
文件名 因此不需要额外的 错误检查 。
示例文件名: 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