![shell 脚本逃离疯狂 - 发送单引号到 subshell](https://linux22.com/image/30527/shell%20%E8%84%9A%E6%9C%AC%E9%80%83%E7%A6%BB%E7%96%AF%E7%8B%82%20-%20%E5%8F%91%E9%80%81%E5%8D%95%E5%BC%95%E5%8F%B7%E5%88%B0%20subshel%E2%80%8B%E2%80%8Bl.png)
我超出了我的技能水平,无法让它正常工作......
#!/bin/bash -x
# mxfbc.sh - mxf video file batch converter
# pass at the command line ...
# (1) the directory to batch convert (typically called CLIPS00X from the Canon XF100 and,
# (2)the file type to convert (typically MXF from the Canon XF100)
# updated 2012-Feb-18
CLIPS_dir="$1"
type="$2"
function ffconvert()
{
# ffmpeg -i "$1" -r 30 -f mov -vcodec libx264 -acodec pcm_s16le -map 0:0 -map 0:1 -map 0:2 "${1%%.*}"\.MOV
ffmpeg -i "$1" -r 30 -f mov -vcodec libx264 -acodec copy -threads 0 -map 0:0 -map 0:1 -acodec copy -map 0:2 -acodec copy "${1%%.*}"\.MOV
# ffmpeg -i "$1" -r 30 -f mov -vcodec copy -acodec pcm_s16le -map 0:0 -map 0:1 -map 0:2 "${1%%.*}"\.MOV
}
#12
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
date
for item in $CLIPS_dir* ; do
if [ -d $item ]; then
inputs=""
map=""
count=0
#echo -e "Item: $item"
for file in $item/* ; do
if [ ${file#*.} = "$type" ]; then
#date
#echo -e "Now processing: ${file##*/} \n"
#echo "File name: ${file%%.*}"
#echo "File type: ${file##*.}"
#inputs="$inputs -i ${file##*/}"
inputs="$inputs -i ""'""$file""'"
map="$map[$count:0] [$count:1] [$count:2] "
count=$(($count+1))
# ffconvert "$CLIPS_dir$item/$file"
# echo -e "Finished processing: ${file##*/} \n"
fi
done
filter=$map
#echo -e $inputs
echo -e $count
#echo -e $map
#echo -e $filter
echo ffmpeg "$inputs"" -r 29.97 -f mov -vcodec libx264 -acodec pcm_s16le -threads 0 -filter_complex ""'""$filter""concat=n=""$count"":v=1:a=2 [v] [a1] [a2]'" -map \'[v]\' -map \'[a1]\' -map \'[a2]\' "'""$item"\.MOV"'"
fi
done
# restore $IFS
IFS=$SAVEIFS
该脚本当前以完美的格式回显 ffmpeg 命令,但我无法让它执行该命令。它总是抱怨“无效参数”的错误。
基本上,我需要在进入子 shell 的命令中传递大量单引号字符。
发送到 subshell 的最终产品如下所示:
ffmpeg -i '/Volumes/localtank/card2/CONTENTS/CLIPS001/AA0715/AA071501.MXF' -i '/Volumes/localtank/card2/CONTENTS/CLIPS001/AA0715/AA071502.MXF' -i '/Volumes/localtank/card2/CONTENTS/CLIPS001/AA0715/AA071503.MXF' -i '/Volumes/localtank/card2/CONTENTS/CLIPS001/AA0715/AA071504.MXF' -i '/Volumes/localtank/card2/CONTENTS/CLIPS001/AA0715/AA071505.MXF' -r 29.97 -f mov -vcodec libx264 -acodec pcm_s16le -threads 0 -filter_complex '[0:0] [0:1] [0:2] [1:0] [1:1] [1:2] [2:0] [2:1] [2:2] [3:0] [3:1] [3:2] [4:0] [4:1] [4:2] concat=n=5:v=1:a=2 [v] [a1] [a2]' -map '[v]' -map '[a1]' -map '[a2]' '/Volumes/localtank/card2/CONTENTS/CLIPS001/AA0715.MOV'
编辑:
好吧...没关系...明白了...感谢您的聆听。对于任何想要从摄像机(自动分段文件)获取文件并使用 ffmpeg 将它们重新加入或连接成连续视频的人,这里有一个脚本。 ...
#!/bin/bash -x
# mxfbcc.sh - mxf video file batch converter and concatenate parts into a whole
# pass at the command line ...
# (1) the directory to batch convert (typically called CLIPS00X from the Canon XF100 and, nothing else
# updated 2013-April-3
CLIPS_dir="$1"
function ffconvert()
{
# ffmpeg -i "$1" -r 30 -f mov -vcodec libx264 -acodec pcm_s16le -map 0:0 -map 0:1 -map 0:2 "${1%%.*}"\.MOV
ffmpeg -i "$1" -r 30 -f mov -vcodec libx264 -acodec copy -threads 0 -map 0:0 -map 0:1 -acodec copy -map 0:2 -acodec copy "${1%%.*}"\.MOV
# ffmpeg -i "$1" -r 30 -f mov -vcodec copy -acodec pcm_s16le -map 0:0 -map 0:1 -map 0:2 "${1%%.*}"\.MOV
}
#12
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
date
for item in $CLIPS_dir* ; do
if [ -d $item ]; then
inputs=""
map=""
count=0
#echo -e "Item: $item"
for file in $item/* ; do
if [ ${file#*.} = "MXF" ]; then
#date
#echo -e "Now processing: ${file##*/} \n"
#echo "File name: ${file%%.*}"
#echo "File type: ${file##*.}"
#inputs="$inputs -i ${file##*/}"
input+="-i '${file}' "
map="$map[$count:0] [$count:1] [$count:2] "
count=$(($count+1))
# ffconvert "$CLIPS_dir$item/$file"
# echo -e "Finished processing: ${file##*/} \n"
fi
done
filter=$map
#echo -e $inputs
#echo -e $count
#echo -e $map
#echo -e $filter
#echo -e
eval ffmpeg ${input} -r 29.97 -f mov -vcodec libx264 -acodec pcm_s16le -threads 0 -filter_complex \'$filter concat=n=$count:v=1:a=2 [v] [a1] [a2]\' -map \'[v]\' -map \'[a1]\' -map \'[a2]\' \'$item\.MOV\'
fi
done
# restore $IFS
IFS=$SAVEIFS
答案1
您不能以这种方式存储文件名列表inputs
:inputs
是一个字符串,您无法区分'
文件名中的空格和添加到字符串中的空格。顺便说一下,inputs="$inputs -i ""'""$file""'"
这是一种令人困惑的书写方式inputs="$inputs -i '$file'"
(即附加一个空格、-i
一个空格、一个单引号、文件名和另一个单引号)。
您的echo
命令打印了一个有效的 shell 命令,因为您在不包含特殊字符的文件名上尝试过它(特别是,没有单引号 - 就该部分而言$inputs
,所有其他字符都可以)。没有echo
,你就在跑步
ffmpeg "$inputs -r 29.97 -f mov -vcodec libx264 -acodec pcm_s16le -threads 0 -filter_complex '${filter}concat=n=$count:v=1:a=2 [v] [a1] [a2]'" \
-map \'[v]\' -map \'[a1]\' -map \'[a2]\' \'$item\.MOV\'
(我简化了多余的引号)。请注意,直到整个字符串[a1] [a2]
都是一个参数。
要存储命令的多个参数,请使用数组。运行该命令时,请在所有变量替换周围使用双引号("$foo"
或对于数组"${foo[@]}"
)。不要在引号周围加上引号,否则您会将文字引号字符传递给ffmpeg
命令。
inputs=()
…
inputs+=(-i "$file")
…
ffmpeg "${inputs[@]}" -r 29.97 -f mov \
-vcodec libx264 -acodec pcm_s16le -threads 0 \
-filter_complex "${filter} concat=n=$count:v=1:a=2 [v] [a1] [a2]" \
-map '[v]' -map '[a1]' -map '[a2]' "$item.MOV"
请注意,您没有将任何单引号传递给任何子 shell(您甚至没有运行子 shell)。引号用于解析脚本,不会将引号传递给任何命令。