私のスクリプトが正しく機能しないのはなぜですか?

私のスクリプトが正しく機能しないのはなぜですか?

私は./script.sh次のように私のものを使用しようとしています:

./compile.sh -n NAME_ALBUM -f 000 000 000 000 -l 000 000 000 000
  • どこ-NALBUM_NAMEで保存されている出力ファイル名に対応します。
  • どこ- F意味 First は、プレイリストで最初に表示されるビデオファイル名のリストです。
  • どこ-エル意味 Last は、プレイリストの最後のビデオファイル名のリストです。

その後、プレイリストが供給されますffmpeg...

#!/bin/sh

# usage: ./compile.sh -n NAME_ALBUM -f 000 000 000 000 -l 000 000 000 000
# OPTION -n is for NAME, video file NAME.
# OPTION -f is for FIRST, video numbers to come FIRST in playlist.
# OPTION -l is for LAST, video numbers to come LAST in playlist.
# NOTE: mp4 videos are numbered as 001.mp4, 002.mp4, 003.mp4
# NOTE: if no videoss are mentioned in -f or -l then it will be ignored by default.
# Q1: possible to use more than (4) videos in -f or -l ?

while getopts ":n:f:l:" options; do

  case "${options}" in
    n)
      $1=${OPTARG}
      ;;
    f)
      $2=${OPTARG}
      ;;
    l)
      $3=${OPTARG}
      ;;
    h)
      echo "Help contents:
            ./compile.sh -n NAME_ALBUM -f 000 000 000 000 -l 000 000 000 000"
      ;;
    :) # not sure what this is
      echo "Error: -${OPTARG} requires an argument." #not sure what this is
      exit_abnormal
      ;;
    *) # or what this ones for
      exit_abnormal
      ;;
  esac
done
exit 0

# mp4 video file name that gets compiled
COMPILED=$1_$(date +'%Y-%m-%d_%H:%M:%S')

# video playlist fed to ffmpeg
VIDEO_LIST=list_$(date +'%Y-%m-%d_%H:%M:%S').txt


find *.mp4 | sed 's:\ :\\\ :g' | sed 's/^/file /' | sort -R  > $VIDEO_LIST; (printf 'g?%s?m0\n' $2 ; printf 'wq\n') | ed -s $VIDEO_LIST; ( printf 'g?%s?m$\n' $3 | tac; echo 'wq'; ) | ed -s $VIDEO_LIST; ffmpeg -f concat -i $VIDEO_LIST -c:v libx264 -crf 12 -preset slow -c:a copy $COMPILED.mp4

私のスクリプトがうまくいかないのは正確に何ですか?

Q:このスクリプトの役割は正確に何ですか?

そのディレクトリのビデオを含むffmpegに必要なプレイリストを作成し(ビデオ名を001.mp4、002.mp4などに変更することをお勧めします。これにより、追加の「最初/最後」オプションを簡単に使用できます) すべてのアイテムを混ぜる。ビデオプレイリストのビデオをffmpegに提供し、1つのビデオにコンパイルします。追加オプション:特定の動画をプレイリストの最初または最後に追加する必要がある場合は、番号を入力してください。スクリプトを実行すると、コマンドラインにファイル名を書き込みます。

答え1

John1024が言及したことに加えて、同様のパラメータは-f file1 file2 file3実際には次のように読み取られます-f file1。最初の値だけがスクリプトとして読み取られ、他の値は失われます。あなたの-l主張も同じだ。

あなたができることは実際に値のリストである文字列を指定することです(値の周りの一重引用符に注意してください)。

./compile.sh -n NAME_ALBUM -f 'file1 file2 file3' -l 'file7 file8 file9'

これにより、次のことが行われます。

  • あなたのオプションの値は ""-fです。file1 file2 file3
  • あなたのオプションの値は ""-lです。file7 file8 file9

ファイル名を取得するために「単に」分割します。次のような構造があなたにインスピレーションを与えます。

f='file1 file2 file3'; for fileName in $f; do echo "$fileName"; done

コメントで質問後に編集:

使用中に見積もりが必要ですか?それともスクリプトに隠すことができますか?私はすでに考えていましたが、スクリプトのコマンドライン使用中に使用する必要があると思いましたが、これは私が望むものではありません。

これは私にとって完全には明確ではありませんが、次のように言うことができます。

  • 'file1 file2 file3'(引用符を含む)は単一の文字列(スペースを含む)であり、変数に保存するか、パラメータ(例-f <value>
  • file1 file2 file3(引用符を除く)は3つの異なる文字列です(スペースがパラメータ区切り文字として機能するため)。-f <value>上記のようなハッキング(引用符など)を使用しない限り、設定の単一パラメータに3つの値を渡すことはできません。

また、$2 $3 $4 $5 は -f で、$6 $7 $8 $9 は -l で使用するのはどうですか?

getopts構文とパラメータを混在させると、$n最終的に読み取れないスクリプトが生成されます。さらに、この$n戦略には正確に4つの値-fと4つの値が含まれます-l

私の提案はまだ、-fそしてオプションのファイルの-lリストを提供し、'file1 file2 file3'スクリプトからそのリストを切り取ることです。

答え2

|これは行の最後の文字として使用でき、行は続きます。

例えば

foo | bar | wc

等しい

foo |
bar |
wc
  • 改行文字のようにコマンドを区別することに注意してください;

スクリプトの最後の部分をインデントし、外部に新しい行を挿入して|から;

最後の行は次のとおりです。

find *.mp4 |
 sed 's:\ :\\\ :g' |
 sed 's/^/file /' | 
 sort -R  > $VIDEO_LIST

 (printf 'g?%s?m0\n' $2 ; printf 'wq\n') |
 ed -s $VIDEO_LIST

 ( printf 'g?%s?m$\n' $3 | tac; echo 'wq'; ) |
 ed -s $VIDEO_LIST

 ffmpeg -f concat -i $VIDEO_LIST -c:v libx264 -crf 12 -preset slow -c:a copy $COMPILED.mp4
  • $2どこで$3?コマンドライン?使用set alpha bravo charly? (他の回答でこの問題を解決します)

  • '\n'2番目のsedで何かが欠けているようです。

  • 冒険者になるスクリプトを次のアドレスに送信してください。https://codereview.stackexchange.com/

関連情報