Bash 在多个文件上运行脚本

Bash 在多个文件上运行脚本

我有一个简单的 bash 脚本,在 ImageMagick 中运行命令。它获取图像(INFILE - 通常为 .tif),调整其大小,然后保存结果(OUTFILE - 通常为 .jpg)

INFILE=/path/'image name.tif'
OUTFILE=/path/'image name.jpg'

echo INFILE="${INFILE}" OUTFILE="${OUTFILE}" 

magick -quiet "${INFILE}" \
  -filter LanczosRadius \
  -distort resize 1600 \
  -quality 92 \
  "${OUTFILE}"

该脚本的名称是Magick-Resize.sh

我想使用此脚本批量处理多个图像 - 也就是说,在多个 INFILES 上运行它。例如。如果一个文件夹中有 100 个图像,我希望每个图像都由该脚本处理一次,为每个图像生成一个唯一的 OUTFILE。

我是 bash 的新手。我用下面的方法破解了它:

INSCRIPT=/path/Magick-Resize.sh

echo INSCRIPT="${INSCRIPT}"

for INFILE in *.tif; do
    if [[ "$INFILE" = *-tagged.tif ]]; then
        continue # skip output
    fi
    name=$(basename "$INFILE")-tagged.jpg
    echo name="${name}"
    "${INSCRIPT}" "$INFILE" > "${name}"
done

但在包含两个 .tif 图像的测试文件夹中,它输出的只是一张文件名为“*.jpg”的图像

有人能够提供解决方案吗?

我使用的是 Mint 20.3

答案1

您的脚本不带任何参数,INFILE 和 OUTFILE 的名称是硬编码在其中的。

在这里,我会使用,zsh代替bash, 并执行以下操作:

transform()
  magick -quiet $1 \
   -filter LanczosRadius \
   -distort resize 1600 \
   -quality 92 \
   $2

autoload -Uz zmv
zmv -P transform './(^*-tagged).tif' './$1-tagged.jpg'

答案2

我展示了另一种解决问题的方法:使用bash.

  • 制作一个 shell 脚本
  • 在顶部放一个 shebang#!/bin/bash来控制哪个 shell 应该运行脚本
  • 创建一个函数,而不是“执行者”部分的单独 shellscript。
  • 从 切换magick到 ,convert因为这就是 Image Magick 工具在我的系统中的实现方式。您可以轻松切换回在您的系统中运行它。
  • 调整批处理部分以使其更加健壮。
    • 添加一些内容# comments以帮助理解发生的情况。当遇到带标签的文件时,跳过,否则创建带标签的jpg文件
    • 对文件名的 bash 变量进行操作和测试,以便仅创建所需的文件。这在man bash关于参数扩展的章节中进行了描述。

请注意如何doer使用两个参数调用该函数,以及它们在函数中如何被视为$1and 。$2

#! /bin/bash -

function doer() {
  INFILE="$1"
  OUTFILE="$2"
  #echo INFILE="${INFILE}" OUTFILE="${OUTFILE}" 
  convert -quiet "${INFILE}" \
    -filter LanczosRadius \
    -distort resize 1600 \
    -quality 92 \
    "${OUTFILE}"
}

#######
# main
#######

shopt -s nullglob
files=(./*.tif)
if (( ${#files[@]} )); then
  # there is at least one tif file, so continue
  for INFILE in "${files[@]}"; do
    if [[ "$INFILE" != *-tagged.tif ]]; then
      # not a tagged tif file, so create variable 'name'
      name="${INFILE%.tif}-tagged.jpg"
      if ! test -s "$name"; then
        # not a tagged jpg file, so create file 'name'
        printf '%s\n' "${name}"
        doer "$INFILE" "${name}"
      fi
    fi
  done
else
  echo >&2 "no tif files found"
  exit 1
fi
echo "normal termination"

答案3

我认为这应该足以满足您的需求:

首先extglob通过运行启用:shopt -s extglob然后

for i in !(*-tagged).tif; do 
    magick "./$i" <flags> "./${i%%.tif}-tagged.jpg"; 
done

这也可以通过 GNU 并行进行简单的并行化:

parallel magick ./{} <flags> ./{.}-tagged.jpg ::: !(*-tagged).tif

相关内容