Linux shell oneliner启动脚本如果文件不存在则不起作用

Linux shell oneliner启动脚本如果文件不存在则不起作用

对于具有指定过滤器的指定目录中的所有文件(png|gif|jpe?g)(!使用\0分隔符以避免文件名带有空格问题),我想查看“优化”webp文件是否存在,以及是否存在不是,转换它。

我知道接下来的内容可以优化等等,但我只是想让它发挥作用。

如果您有更好的解决方案(有解释!)当然,这也很有趣。

IFS= readarray -t -d '' tab < <(find . -type f -print0  | grep -zZE "(png|gif|jpe?g)$") && for f in "${tab[@]}"; do if [ ! -f "$f.webp" ]; then cwebp -q 80 "$f" -o "$f.webp"; fi done

这就是我所做的:我正在通过readarray所有找到的与我的模式匹配的文件创建一个数组。然后我对它们进行循环,测试文件是否存在。如果没有,我称cwebp -q 80 "$f" -o "$f.webp";This one does not work 并出现以下错误。为什么?

Error! Could not process file ./08/10700_header.jpg
Error! Cannot read input picture file './08/10700_header.jpg'
Error! Could not process file ./08/205790_header.jpg
Error! Cannot read input picture file './08/205790_header.jpg'

答案1

bash 中更好的解决方案:你实际上不需要找到:

shopt -s extglob  # extended pattern match, you likely already have it set
shopt -s globstar # extended directory level search ('**' matches any directory level)

for f in **/*.@(jpg|jpeg|png|gif)
do 
    [[ -f "$f.webp" ]] || cwebp -q 80 "$f" -o "$f.webp"
done

要运行,parallel我们必须删除已经完成的文件,以便我们可以cwebp直接调用。一种方法是使用 webp 文件列表过滤文件列表:

printf '%s\n' **/*.@(jpg|jpeg|png|gif) \
    | grep -vf <(printf '%s\n' **/*.webp | sed 's/\.webp$//') \
    | parallel -i cwebp -q 80 {} -o {}.webp

慢动作:

  • printf '%s\n' **/*.@(jpg|jpeg|png|gif)生成所有可能候选者的列表作为流(因为这是printf内置的 i,在 bash 中它不受命令行约束)
  • grep -vf <(printf '%s\n' **/*.webp | sed 's/\.webp$//')从该列表中删除所有已关联的文件.webp(通过列出*.webp文件、截断其扩展名并将结果用作grep模式列表)
  • parallel -i cwebp -q 80 {} -o {}.webp将结果提供给并行执行。

请注意,由于parallel似乎没有参数来接受以 null 结尾的输入,因此您只需要希望没有奇怪的文件名即可。

预过滤技术也可用于非并行情况。

答案2

我不完全确定是什么产生了您显示的错误或原因,但大概是在cwebp查找您提供的路径名时遇到了问题。

我会让find找到相关文件并执行循环,而不是使用grep临时数组:

find . \( -name '*.png' -o -name '*.gif' -o -name '*.jpg' -o -name '*.jpeg' \) \
        -type f -exec sh -c '
        for pathname do
                [ -f "$pathname.webp" ] && continue
                cwebp -q 80 "$pathname" -o "$pathname.webp"
        done' sh {} +

在这里,我用作find内联脚本的一种路径名生成器sh -c。内联脚本批量获取路径名并循环它们。对于每个给定的路径名​​,如果相应的.webp文件存在,则循环跳到下一个路径名。否则,cwebp将调用该命令。

这避免了奇怪的文件或目录名的问题,并且可以移植到任何已cwebp安装的系统(find命令本身是标准的,内联脚本也是如此)。

也可以看看 ”了解“find”的 -exec 选项" 有关-exec sh -c '...' sh {} +语法的更多信息。

如果这仍然不起作用,您可能需要调查报告的图像文件以确保它们确实是有效的图像文件。

相关内容