?4 がこの Bash スクリプトのファイル名に追加されます。なぜですか?

?4 がこの Bash スクリプトのファイル名に追加されます。なぜですか?

mp4私は大量のビデオからフレームを抽出して次のように保存するスクリプトを持っています。png

for i in *.mp4; do
    [ -f "$i" ] || break
    number=$(echo "$i" | grep -o -E '[0-9]+')
    name=frame"$number".png
    ffmpeg -i "$i" -ss 00:01:00.000 -vframes 1 "$name"
done

動画名は背中に似ていますvideo1.mp4video2.mp4ループがビデオをミックスするため、ビデオから数字を抽出して出力ファイル名を生成します。

これはうまくいきますが、ファイル名は次のpngとおりです。

frame1?4.png, frame3?4.png, frame3?4.png...

なぜ?4


ああ、今見ると、mp4の4から4が出てきます。最初の数字だけをどのように取得できますか?

ベストアンサー1

これは、ファイル名に含まれる改行のプレースホルダ?出力にすぎません。ls

echo foo3bar.mp4 | grep -Eo '[0-9]+'

出力されます:

3
4

これは、ファイル名に1つ以上の10進数で構成される2つのシーケンスが含まれているためです。

代わりに、次のようにすることができます。

for file in *[0-9]*.mp4; do
  n=${file%.*} # remove the extension
  n=${n%"${n##*[0-9]}"} # remove anything after the last digit
  n=${n##*[!0-9]} # remove everything up to the last non-digit.

  ffmpeg...
done

これにより、ファイル名から一番右の10進数シーケンスを抽出し、拡張子を削除して各ファイルに対して複数のコマンドを実行する必要がなくなります。

bashこのコードは標準のPOSIX sh構文のみを使用するため、実行する必要はありません。bashまたは、他のksh93同様のシェルがファイルのルート名に一連の数字のみが含まれていることがわかっている場合は、次のようにすることもできます。

n=${file%.*} # remove the extension
n=${n//[^0-9]} # remove all non-digit characters

特定の機能がありますbash

[[ $file =~ ([0-9]+).*\. ]] && n=${BASH_REMATCH[1]}

抽出する一番左ルート名の数値順です。

そしてzsh

n=${(SM)${file:r}##<->}

おすすめ記事