解析Shell Bash脚本的值

时间:2021-07-26 00:10:55

I am trying to make a simple bash script for a command so i can make it reusable for me the command has been taken from another post to convert videos with ffmpeg then upload.

我正在尝试为命令创建一个简单的bash脚本,所以我可以让它可以重用,我从另一个帖子中获取命令,用ffmpeg转换视频然后上传。

Here is what i have so far.

这是我到目前为止所拥有的。

#!/bin/bash
MOVIES=$1
EXT=$2
BUCKET=$3
find "$MOVIES" -name "*.$EXT" -exec sh -c 'ffmpeg -i "$0" -c:v libx264 -crf 22 -c:a libfaac -movflags faststart "${0%%.mov}.mp4" && s3cmd put "${0%%.mov}.mp4" "$BUCKET""$(basename "${0%%.mov}.mp4")"' {} \;
exit;

I am having issues with the third var if i run it like this.

如果我像这样运行它,我遇到第三个var的问题。

sh batch.sh ~/Documents/screengrabs/ mov s3://bucket/

I am getting a error it encodes properly.

我收到正确编码的错误。

ERROR: Parameter problem: Destination must be S3Uri. Got: file://49A22352-9F41-48B9-BF97-610CBF699025-630-0000055828D0D55F.mp4

This means it is not parsing the $3 parameter $BUCKET properly.

这意味着它没有正确解析$ 3参数$ BUCKET。

Any help this is my first bash script attempt.

任何帮助这是我的第一个bash脚本尝试。

Thanks

Update still not working

更新仍无效

#!/bin/bash
MOVIES="$1"
EXT="$2"
BUCKET="$3"

find "$MOVIES" -name "*.${EXT}" -exec sh -c 'ffmpeg -i "$0" -c:v libx264 -crf 22 -c:a libfaac -movflags faststart "${0%%.mov}.mp4" && s3cmd put "${0%%.mov}.mp4" "${BUCKET}/sam.mp4"' {} \;

exit;

WORKING

#!/bin/bash
MOVIES=$1
EXT=$2
export BUCKET=$3
find "$MOVIES" -name "*.$EXT" -exec sh -c 'ffmpeg -i "$0" -c:v libx264 -crf 22 -c:a libfaac -movflags faststart "${0%%.mov}.mp4" && s3cmd put "${0%%.mov}.mp4" "$BUCKET""$(basename "${0%%.mov}.mp4")"' {} \;
exit;

2 个解决方案

#1


1  

The problem is that $0 is the name of the script that is executed (in this case a temporary file created by sh from the argument to -c), not the first argument to the resulting script. Note that the error message does not mention a file with sam in the name, so it is being generated by the ${0%%.mov}.mp4 argument to s3cmd, not the one that uses $BUCKET. Replace it with $1. Also, you need to export BUCKET so that the shell started by find has access to it. (The literal string $BUCKET, not its value, is passed to sh via its -c option because the string is rightly single-quoted.)

问题是$ 0是执行的脚本的名称(在这种情况下是由参数sh创建的临时文件到-c),而不是生成的脚本的第一个参数。请注意,错误消息未提及名称中带有sam的文件,因此它是由s3cmd的$ {0 %%。mov} .mp4参数生成的,而不是使用$ BUCKET的参数。替换为1美元。此外,您需要导出BUCKET,以便由find启动的shell可以访问它。 (文字字符串$ BUCKET,而不是它的值,通过其-c选项传递给sh,因为该字符串是正确的单引号。)

(UPDATE: as Etan pointed out, $0 is correct.)

(更新:正如Etan指出的那样,$ 0是正确的。)

#!/bin/bash
MOVIES=$1
EXT=$2
export BUCKET=$3
find "$MOVIES" -name "*.$EXT" -exec sh -c 'ffmpeg -i "$0" -c:v libx264 -crf 22 -c:a libfaac -movflags faststart "${1%%.mov}.mp4" && s3cmd put "${0%%.mov}.mp4" "$BUCKET""$(basename "${0%%.mov}.mp4")"' {} \;
exit;

In bash 4, however, I would just write

然而,在bash 4中,我只会写

#!/bin/bash
MOVIES=$1
EXT=$2
BUCKET=$3

shopt -s globstar
for movie in "$MOVIES"/**/*."$EXT"; do
    mp4movie=${movie%%.mov}.mp4
    ffmpeg -i "$movie" -c:v libx264 -crf 22 -c:a libfaac -movflags faststart "$mp4movie" &&
      s3cmd put "$mp4movie" "$BUCKET/$mp4movie"
done

This is much easier to get right than trying to cram a small script into a single string for sh -c.

这比试图将一个小脚本塞入sh -c的单个字符串要容易得多。


Manual recursive search with bash 3.2:

使用bash 3.2进行手动递归搜索:

process_file () {
    movie=$1
    mp4movie=${movie%%.mov}.mp4
    ffmpeg -i "$movie" -c:v libx264 -crf 22 -c:a libfaac -movflags faststart "$mp4movie" &&
      s3cmd put "$mp4movie" "$BUCKET/$mp4movie"
}

process_directory () {
    dir=$1
    for name in "$dir"/*; do
        if [[ -d "$name" ]]; then
            process_directory "$name"
        elif [[ -f $name && $name = *.$EXT ]]; then 
            process_file "$name"
        fi
    done
}

MOVIES=$1
EXT=$2
BUCKET=$3
process_directory "$MOVIES"

#2


0  

@chepner's answer about using a "native" shell script is a good one. That being said, and as I just posted in a comment on the OP, I believe the issue here is simply a variable scope issue.

@chepner关于使用“原生”shell脚本的答案很好。话虽如此,正如我刚刚在对OP的评论中发表的那样,我认为这里的问题只是一个可变范围问题。

If you edit the script to use "$1" instead of "$BUCKET" in the script passed to sh -c and add "$BUCKET" between the {} and \; I believe the script will work (though I haven't fully evaluated the script in other respects).

如果编辑脚本在传递给sh -c的脚本中使用“$ 1”而不是“$ BUCKET”,并在{}和\之间添加“$ BUCKET”;我相信脚本会起作用(尽管我还没有在其他方面对脚本进行全面评估)。

#1


1  

The problem is that $0 is the name of the script that is executed (in this case a temporary file created by sh from the argument to -c), not the first argument to the resulting script. Note that the error message does not mention a file with sam in the name, so it is being generated by the ${0%%.mov}.mp4 argument to s3cmd, not the one that uses $BUCKET. Replace it with $1. Also, you need to export BUCKET so that the shell started by find has access to it. (The literal string $BUCKET, not its value, is passed to sh via its -c option because the string is rightly single-quoted.)

问题是$ 0是执行的脚本的名称(在这种情况下是由参数sh创建的临时文件到-c),而不是生成的脚本的第一个参数。请注意,错误消息未提及名称中带有sam的文件,因此它是由s3cmd的$ {0 %%。mov} .mp4参数生成的,而不是使用$ BUCKET的参数。替换为1美元。此外,您需要导出BUCKET,以便由find启动的shell可以访问它。 (文字字符串$ BUCKET,而不是它的值,通过其-c选项传递给sh,因为该字符串是正确的单引号。)

(UPDATE: as Etan pointed out, $0 is correct.)

(更新:正如Etan指出的那样,$ 0是正确的。)

#!/bin/bash
MOVIES=$1
EXT=$2
export BUCKET=$3
find "$MOVIES" -name "*.$EXT" -exec sh -c 'ffmpeg -i "$0" -c:v libx264 -crf 22 -c:a libfaac -movflags faststart "${1%%.mov}.mp4" && s3cmd put "${0%%.mov}.mp4" "$BUCKET""$(basename "${0%%.mov}.mp4")"' {} \;
exit;

In bash 4, however, I would just write

然而,在bash 4中,我只会写

#!/bin/bash
MOVIES=$1
EXT=$2
BUCKET=$3

shopt -s globstar
for movie in "$MOVIES"/**/*."$EXT"; do
    mp4movie=${movie%%.mov}.mp4
    ffmpeg -i "$movie" -c:v libx264 -crf 22 -c:a libfaac -movflags faststart "$mp4movie" &&
      s3cmd put "$mp4movie" "$BUCKET/$mp4movie"
done

This is much easier to get right than trying to cram a small script into a single string for sh -c.

这比试图将一个小脚本塞入sh -c的单个字符串要容易得多。


Manual recursive search with bash 3.2:

使用bash 3.2进行手动递归搜索:

process_file () {
    movie=$1
    mp4movie=${movie%%.mov}.mp4
    ffmpeg -i "$movie" -c:v libx264 -crf 22 -c:a libfaac -movflags faststart "$mp4movie" &&
      s3cmd put "$mp4movie" "$BUCKET/$mp4movie"
}

process_directory () {
    dir=$1
    for name in "$dir"/*; do
        if [[ -d "$name" ]]; then
            process_directory "$name"
        elif [[ -f $name && $name = *.$EXT ]]; then 
            process_file "$name"
        fi
    done
}

MOVIES=$1
EXT=$2
BUCKET=$3
process_directory "$MOVIES"

#2


0  

@chepner's answer about using a "native" shell script is a good one. That being said, and as I just posted in a comment on the OP, I believe the issue here is simply a variable scope issue.

@chepner关于使用“原生”shell脚本的答案很好。话虽如此,正如我刚刚在对OP的评论中发表的那样,我认为这里的问题只是一个可变范围问题。

If you edit the script to use "$1" instead of "$BUCKET" in the script passed to sh -c and add "$BUCKET" between the {} and \; I believe the script will work (though I haven't fully evaluated the script in other respects).

如果编辑脚本在传递给sh -c的脚本中使用“$ 1”而不是“$ BUCKET”,并在{}和\之间添加“$ BUCKET”;我相信脚本会起作用(尽管我还没有在其他方面对脚本进行全面评估)。