max(x) = 9999prefix_0000.mp3
というファイルのリストがあります。prefix_x.mp3
Bashスクリプトがあります。
...
sox prefix_*.mp3 script_name_output.mp3 # this fails because maximum number is 348
rm prefix_*.mp3
...
ソートされたmp3ファイルのリストをサブリスト(順番に保持)に分割し、徐々に削除し、sox
bashスクリプトから不要なファイルを削除する最善の方法は何ですか?
ベストアンサー1
まず、リストを Bash 配列として収集します。ファイルが現在のディレクトリにある場合は、次のものを使用できます。
files=(prefix_????.mp3)
または、検索と並べ替えを使用できます。
IFS=$'\n' ;
files=($(find . -name 'prefix_*.mp3' printf '%p\n' | sort -d))
この設定はIFS
Bash に改行文字でのみ分割するよう指示します。ファイル名とディレクトリ名にスペースが含まれていない場合は省略できます。
または、ファイルからファイル名を読み取ることができます(たとえば、filelist
1行に1つの名前、空白行なし)。
IFS=$'\n'
files=($(<filelist))
空白行がある場合は、以下を使用してください。
IFS=$'\n'
files=($(sed -e '/$/ d' filelist))
次に、各スライスに必要なファイル数、一時アキュムレータファイル名、最終結合ファイル名を決定します。
s=100
src="combined-in.mp3"
out="combined-out.mp3"
その後、リストを分割して各サブリストを処理します。
while (( ${#files[@]} > 0 )); do
n=${#files[@]}
# Slice files array into sub and left.
if (( n <= s )); then
sub=("${files[@]}")
left=()
else
(( n-= s ))
sub=("${files[@]:0:s}")
left=("${files[@]:s:n}")
fi
# If there is no source file, but there is
# a sum file, rename sum to source.
if [ ! -e "$src" -a -e "$out" ]; then
mv -f "$out" "$src"
fi
# If there is a source file, include it first.
if [ -e "$src" ]; then
sub=("$src" "${sub[@]}")
fi
# Run command.
if ! sox "${sub[@]}" "$out" ; then
rm -f "$out"
echo "Failed!"
break
fi
rm -f "$src"
echo "Done up to ${sub[-1]}."
files=("${left[@]}")
# rm -f "${sub[@]}"
done
報告が失敗すると、sox
ループは早期に終了します。それ以外の場合は、処理されたバッチの姓を出力します。
if
for コマンドを使用してsox
エラーを検出し、エラーが発生した場合は出力ファイルを削除します。また、コマンドが成功するまで配列の変更を延期files
するので、sox
個々のファイルを安全に編集/修正してからループを再実行して、中断したwhile
部分から続行できます。
ディスク容量が不足している場合は、最後から2行目のコメントを外して、正常にマージされたすべてのrm -f "${sub[@]}"
ファイルを削除できます。
上記は、最初の部分を取り上げ続けています。
ffmpeg
以下の説明で説明するように、sox
最初にファイルをリンクしてから(再エンコードを使用せずに)再エンコードを使用すると、結果がはるかに良くなりますsox
。 (またはもちろん、最初に録音することもできます。)
まず、パイプで区切られたファイル名(文字列)のリストを作成し、
files="$(ls -1 prefix_????.mp3 | tr '\n' '|')"
最後の余分なチューブを取り外し、
files="${files%|}"
記録せずに供給しますffmpeg
。
ffmpeg -i "concat:$files" -codec copy output.mp3
実行したいかもしれません
ulimit -n hard
開いているファイルの数を現在のプロセスで許可される最大値に増やします(ハード制限);を使用してクエリを実行できますulimit -n
。 (ffmpeg
concat:
ソースを順次オープンするか、一度にオープンするかはよく覚えていません。)
これを何度も実行する場合は、すべてを簡単なスクリプトに入れます。
#!/bin/bash
export LANG=C LC_ALL=C
if [ $# -le 2 -o "$1" = "-h" -o "$1" = "--help" ]; then
exec >&2
printf '\n'
printf 'Usage: %s -h | --help ]\n' "$0"
printf ' %s OUTPUT INPUT1 .. INPUTn\n' "$0"
printf '\n'
printf 'Inputs may be audio mp3 or MPEG media files.\n'
printf '\n'
exit 1
fi
output="$1"
shift 1
ulimit -n hard
inputs="$(printf '%s|' "${@}")"
inputs="${inputs%|}"
ffmpeg -i "concat:$inputs" -codec copy "$output"
retval=$?
if [ $retval -ne 0 ]; then
rm -f "$output"
echo "Failed!"
exit $retval
fi
# To remove all inputs now, uncomment the following line:
# rm -f "${@}"
echo "Success."
exit 0
私はMPEGを使用しているので、上記は-codec copy
mp3-acodec copy
オーディオファイルだけでなく、あらゆる種類のMPEGファイルに適用する必要があります。