0

ここにスクリプトがあります.. bashのスキルを練習して、中国のmp4プレーヤー用の簡単なユーティリティを作りたいだけです=)

#!/bin/bash

#####################################
# RockChip 4gb Player mencoder preset
#####################################

TOOL='mencoder'
OUTS='./out/'
OPT1='-noodml'
OPT2="-of avi -ofps 22 -vf-add scale=320:-2,expand=320:240 -srate 44100 -ovc xvid -xvidencopts bitrate=400:max_bframes=0:quant_type=s16le -oac lavc -lavcopts acodec=mp2:abitrate=128"

bold=`tput bold`
normal=`tput sgr0`

# check does argument exists
if test -z "$1"; then
  echo "There's no file given =)"
fi

# Check is it dir or file

if [ -d $1 ]; then
  echo "Directory is given: $1"

  # Test if output argument is given
  if [ -z $2 ]; then
        echo "No output argument given using default: ${bold}${red}$OUTS${normal}"
        mkdir out
  else
      # test is given path a directory
        if [ -d $2 ]; then
                OUT="$2"
        else
           echo "Output argument is not a directory"
        fi
   fi

OLD_IFS=IFS; IFS=$'\n'

for file in `find . -name "*.*" -type f | sed 's!.*/!!'` ; do
        file=`printf "%q" "$file"`
echo    ${TOOL} ${OPT1} ${file} -o ${OUTS}${file} ${OPT2}
done

IFS=OLD_IFS

fi

問題はこの行です:

echo    ${TOOL} ${OPT1} ${file} -o ${OUTS}${file} ${OPT2}

echo を削除してコマンドを実行すると、コマンドは失敗しますが、このエコーされたスクリプトをコピーして手動で実行すると、すべてが機能します。

シェル スクリプトの出力からコマンドを実行すると、次のようになります。

MEncoder 1.0rc4-4.2.1 (C) 2000-2010 MPlayer Team
158 audio & 340 video codecs
-of avi -ofps 22 -vf-add scale=320:-2,expand=320:240 -srate 44100 -ovc xvid -xvidencopts bitrate=400:max_bframes=0:quant_type=s16le -oac lavc -lavcopts acodec=mp2:abitrate=128 is not an MEncoder option

Exiting... (error parsing command line)

コマンドを手動で実行する前に述べたように、たとえば次のようにすべてが機能します。

mencoder -noodml 12\ I\ Love\ You\ 1\ \ I\ Love\ You\ 2\ \ I\ Love\ You\ 3.avi -o ./out/12\ I\ Love\ You\ 1\ \ I\ Love\ You\ 2\ \ I\ Love\ You\ 3.avi -of avi -ofps 22 -vf-add scale=320:-2,expand=320:240 -srate 44100 -ovc xvid -xvidencopts bitrate=400:max_bframes=0:quant_type=s16le -oac lavc -lavcopts acodec=mp2:abitrate=128

今私ができることは、生成されたコマンドをコピーして貼り付けることだけです..どこに問題がありますか? 私は本当に懸命にグーグルを試みました..結果はありません...(私はmencoderがプロファイルを持っていることを知っています..私がそれらを望む場合ではありません)

4

5 に答える 5

1

あなたは持っています(私が信じる37行目):

OUT="$2"

しかし、私はあなたが意味したと思います:

OUTS="$2"
于 2011-04-21T04:35:46.967 に答える
1

まず、$()バックティックの代わりに使用します。

bold=$(tput bold)
normal=$(tput sgr0)

OLD_IFS=IFS; IFS=$'\n'する必要がありますOLD_IFS=$IFS。IFS の値を取得したいので、ドル記号を付けます。

sedファイルのベース名を取得するために呼び出す必要はありません

while read -r  file
do
    filename="${file##*/}"
    filename=$(printf "%q" $filename)
    echo mencoder "${OPT1}" "${file}" -o "${OUTS}${file}" "${OPT2}"
done < <(find . -name "*.*" -type f)

最後に、

IFS=OLD_IFSする必要がありますIFS=$OLD_IFS

于 2011-04-21T05:55:55.143 に答える
1

完全にはわかりませんが、ファイル名を二重引用符 ( ") で囲むのではなく、引用符で囲む方がよいかもしれませんprintf "%q" "$file"

したがって、次のように置き換えます。

file=`printf "%q" "$file"`
${TOOL} ${OPT1} ${file} -o ${OUTS}${file} ${OPT2}

${TOOL} ${OPT1} "${file}" -o "${OUTS}${file}" ${OPT2}
于 2011-04-21T04:45:44.220 に答える
0

forループの前に次のステートメントがあります。

IFS=$'\n'

これにより、空白に一致するデフォルトの代わりに、内部フィールドセパレーターが改行に設定されます。これにより、置換されたパラメーターの解析方法が変わります。コマンドを構築する行で:

${TOOL} ${OPT1} ${file} -o ${OUTS}${file} ${OPT2}

何が起こるかというと、これらの${variable}式のそれぞれが展開され、シェルは、\n通常期待する空白ではなく、 でそれらを分割しようとします。次のように同様の結果が得られます (これらの変数のいずれかに改行が含まれていない場合)。

"${TOOL}" "${OPT1}" "${file}" -o "${OUTS}${file}" "${OPT2}"

${OPT2}ここでは、Bash が文字列をスペースで分割して各フラグを個別に渡すのではなく、文字列全体を 1 つのパラメーターとして渡していることがわかります。mencoder次に、対処方法がわからないこの1つの巨大なパラメーターに混乱します。もちろん、スペースはすべて残っているため、コマンドによって出力され、リセットされていないechoシェルで正常に動作します。$IFS

各引数を別々の行に出力する単純な関数を定義することで、この効果を非常に簡単に実証できます。

$ print_args() { for arg; do echo $arg; done }
$ foo="1 2"
$ print_args ${foo} ${foo}
1
2
1
2
$ IFS=$'\n'
$ print_args ${foo} ${foo}
1 2
1 2

ループに$IFSトリックを使用しないことをお勧めします。代わりに、入力の各行を反復処理するためにfor使用できます。while read fileまた、スペースのエスケープには を使用しないことをお勧めしprintf "%q"ますが、代わりに引数を に引用するだけでmencoder、全体が 1 つの引数として渡されます。私は引用していて、それらがそれぞれ単一の引数として渡されることを確認していますが、シェルによって個別の引数として解析できるようにするために引用していないことに注意${file}${OUTS}${file}てください${OPT1}${OPT2}

find . -name "*.*" -type f | sed 's!.*/!!' | while read -r file
do 
    "${TOOL}" ${OPT1} "${file}" -o "${OUTS}${file}" ${OPT2}
done

ちなみに、$()コマンド置換ではなく``;を使用することをお勧めします。読みやすさ、より適切な引用符とエスケープ規則、複数レベルのコマンド置換をネストする機能など、多くの理由があります。そして、Jonathan と Wes が指摘する問題は注目に値しますが、それらが差し迫った問題の原因ではありません。

于 2011-04-21T04:54:04.850 に答える