在 Bash 中处理通过命令行传递的文件中 FOR 循环内带有空格的文件失败

在 Bash 中处理通过命令行传递的文件中 FOR 循环内带有空格的文件失败

我正在创建一个裁剪电影的脚本,其语法如下:

 ./crop *.mov 0,0,100,100

或者

./crop oneMovie.mov 0,0,100,100

因此,第一个参数可以是通配符模式或一个特定的文件。

我知道$2等于0,0,100,100,这是裁剪参数。

所以,$1将会传递文件。

现在我需要创建一个循环来处理这些文件。

以下是使用的一些变量

fileEnd="-CROPPED.mov"
outputFile="$fileName$fileEnd"

所以我有一个像这样的循环

for f in $1
  // crop video
  ffmpeg -i "$f" -filter:v "crop=$w:$h:$x:$y" "$outputFile"
done

如果文件名称中有空格,则此操作会失败。

我认为问题之一是对于带有空格的文件来说$2不会有参数(参见下面的脚本)。

调用脚本crop "*.mov" x,y,w,h是可行的,但我想让它在没有这种“黑客攻击”的情况下工作,因为我知道当我调用脚本时我会忘记这一点。

$f和的引用$outputFile都用引号括起来。这难道不可以吗?

这是完整的脚本

#!/bin/bash

# syntax crop *.mov x,y,w,h
# or
# crop oneFile.mov x,y,w,h


fileEnd="-CROPPED.mov"    

x=0
y=0
w=0
h=0

# get the crop values
if [ $# -eq 2 ]
then
  argumentCrop=$2
  IFS=',' read -r -a array <<< "$argumentCrop"
  x="${array[0]}"
  y="${array[1]}"
  w="${array[2]}"
  h="${array[3]}"
fi

for f in $1
do

  filename="${f%%.*}"

  outputFile="$filename$fileEnd"

  ffmpeg -i "$f" -filter:v "crop=$w:$h:$x:$y" "$outputFile"

done

答案1

我建议你改变你的调用:

./crop 0,0,100,100 *.mov

然后,在您的脚本中,您将执行以下操作:

IFS=, read -r x y w h <<<"$1"
shift

for f in "$@"; do 
    outputFile=${f%.mov}-CROPPED.mov
    ffmpeg -i "$f" -filter:v "crop=$w:$h:$x:$y" "$outputFile"
done

你遇到的问题是外壳会膨胀*.mov 启动你的脚本,也是$2如此不保证作为裁剪几何,除非只有一个 .mov 文件。$1不是文件列表,而是单个文件。


另一种方法是将裁剪几何形状作为选项传递:

./crop -x 0 -y 0 -x 100 -y 100 *.mov

然后

#!/usr/bin/env bash

x=0 y=0 w=150 h=75   # provide some default values

while getopts :Hw:h:x:y: opt; do
    case $opt in
        w) w=$OPTARG ;;
        h) h=$OPTARG ;;
        x) x=$OPTARG ;;
        y) y=$OPTARG ;;
        ?) echo "usage: $0 -w w -h h -x x -y y file.mov ..."; exit ;;
    esac
done
shift $((OPTIND-1))

for f in "$@"; do 
    outputFile=${f%.mov}-CROPPED.mov
    ffmpeg -i "$f" -filter:v "crop=$w:$h:$x:$y" "$outputFile"
done

相关内容