Bash脚本:无法执行mencoder命令!

| 这是一个脚本..只是想练习一些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有配置文件..不是我想要它们的情况)     
已邀请:
for
循环之前,您具有以下语句:
IFS=$\'\\n\'
这会将您的内部字段分隔符设置为换行符,而不是匹配任何空格的默认值。这改变了替换参数的解析方式。在构造命令的行中:
${TOOL} ${OPT1} ${file} -o ${OUTS}${file} ${OPT2}
将会发生的是,每个those7ѭ表达式都将被扩展,然后外壳程序将尝试在
\\n
上拆分它们,而不是通常希望的空白。它将为您提供与以下类似的结果(除非这些变量之一包含换行符):
\"${TOOL}\" \"${OPT1}\" \"${file}\" -o \"${OUTS}${file}\" \"${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
遍历输入中的每一行。我还建议不要使用ѭ18来转义空格,而只需引用ѭ11的参数,它将把整个内容作为单个参数传递。请注意,我要引用
${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
顺便说一句,我建议您使用ѭ25代替命令ѭ26来代替命令。之所以选择它是有很多原因的,例如可读性,更合理的引用和转义规则以及嵌套多个级别的命令替换的能力。乔纳森(Jonathan)和韦斯(Wes)指出的问题值得一提,尽管它们并不是引起您直接问题的原因。     
您有(我相信第37行):
OUT=\"$2\"
但我认为您的意思是:
OUTS=\"$2\"
    
我不太确定,但最好用双引号(
\"
)引用文件名,而不要用file30ѭ。 因此,请替换:
file=`printf \"%q\" \"$file\"`
${TOOL} ${OPT1} ${file} -o ${OUTS}${file} ${OPT2}
${TOOL} ${OPT1} \"${file}\" -o \"${OUTS}${file}\" ${OPT2}
    
首先,使用ѭ25而不是反tick。
bold=$(tput bold)
normal=$(tput sgr0)
OLD_IFS=IFS; IFS=$\'\\n\'
应该是
OLD_IFS=$IFS
。您想获得IFS的价值,因此请加一个美元符号。 您无需致电ѭ37即可获取文件的基本名称
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
    
使用
... | 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}\"
    

要回复问题请先登录注册