簡體   English   中英

Bash腳本:無法執行mencoder命令!

[英]Bash Script: Can't execute mencoder command!

這是一個腳本..只是想練習一些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,執行命令時,命令失敗,但是如果您復制此回顯腳本並手動執行,則一切正常。

從shell腳本執行命令時,輸出為:

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有個人資料..不是我想要他們的情況)

您有(我相信第37行):

OUT="$2"

但我認為您的意思是:

OUTS="$2"

我不確定,但是最好用雙引號( " )引用文件名,而不是用printf "%q" "$file"代替。

因此,請替換:

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

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

首先,使用$()而不是反向刻度。

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

OLD_IFS=IFS; IFS=$'\\n' 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

for循環之前,您具有以下語句:

IFS=$'\n'

這會將您的內部字段分隔符設置為換行符,而不是匹配任何空格的默認值。 這改變了替換參數的解析方式。 在構造命令的行中:

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

將會發生的是,每個${variable}表達式都將被擴展,然后外殼程序將嘗試在\\n而不是您通常期望的空白處拆分它們。 它將為您提供與以下類似的結果(除非這些變量之一包含換行符):

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

在這里,您可以看到您將整個${OPT2}字符串作為單個參數${OPT2} ,而不是讓Bash在空格上將其分割並分別傳遞每個標志。 然后, mencoder對這個不知道如何處理的巨大參數感到困惑。 當然,由於所有空格仍然存在,它們將通過echo命令打印出來,並且在$IFS尚未重置的shell中可以正常工作。

通過定義一個簡單的函數,可以在單獨的行上打印其每個參數,可以非常輕松地演示這種效果:

$ 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

我建議不要在for循環中使用$IFS技巧。 相反,您可以使用while read file來迭代輸入中的每一行。 我也建議不要使用printf "%q"來轉義空格,而只需將參數引用給mencoder ,它將把整個事情作為單個參數傳遞。 請注意,我引用${file}${OUTS}${file}以確保它們作為單個參數傳入,但不引用${OPT1}${OPT2}以便允許它們被shell解析為單獨的參數。

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

順便說一句,我建議您使用$()代替命令而不是`` ; 之所以選擇它,是有很多原因的,例如可讀性,更合理的引用和轉義規則以及嵌套多個級別的命令替換的能力。 喬納森和韋斯指出的問題值得一提,盡管它們並不是引起您直接問題的原因。

使用... | xargs bash -c '...' ... | xargs bash -c '...'您只需要對文件名中的嵌入式單引號進行轉義。

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'

# test cases
file='12 I Love You 1  I Love You 2  I Love You 3.avi'   
file='12 I Lo"ve You 1  I Love You 2  I Love You 3.avi'   # one embedded double quote
file='12 I Lo"ve You 1  I Lo"ve You 2  I Love You 3.avi'  # two embedded double quotes
file="12 I Lo've You 1  I Love You 2  I Love You 3.avi"   # one embedded single quote
file="12 I Lo've You 1  I Lo've You 2  I Love You 3.avi"  # two embedded single quotes

# escape embedded single quotes in $file
escsquote="'\''"
file="${file//\'/${escsquote}}"

# we're passing ${TOOL} as arg0 to bash -c (which then is available as "$0")
# put the variables in the printf line into single quotes to preserve spaces
# remove no-op ':' to execute the command

printf '%s\n' "${file}"

printf '%s' "${OPT1} '${file}' -o '${OUTS}${file}' ${OPT2}" | 
    xargs bash -c 'set -xv; printf "%s\n" "$0" "$@" | nl' "${TOOL}"

printf '%s' "${OPT1} '${file}' -o '${OUTS}${file}' ${OPT2}" | 
    xargs bash -c 'set -xv; : "$0" "$@"' "${TOOL}"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM