bash ファイル名から最初の数字を抽出します

bash ファイル名から最初の数字を抽出します

次のようにファイルを移動しようとしています:

...
DLG023-00-01-sprite.TextGrid.json
DLG023-00-01.prosody.json
DLG023-01-01-sprite.ogg
DLG023-00-02-sprite.TextGrid.json
DLG023-00-02.prosody.json
DLG023-01-02-sprite.ogg
...
DLG028-00-01-sprite.TextGrid.json
DLG028-00-01.prosody.json
DLG028-01-01-sprite.ogg
...

それぞれのフォルダーに移動します。たとえば、ファイルが ;dialogue023/で始まる場合は に移動し、 ;で始まる場合DLG023は に移動します。dialogue024/DLG024

すべてのファイルとディレクトリは同じレベルにあります。

つまり、次のようなコマンドを生成しようとしています。

mv DLG023-00-01-sprite.ogg dialogue023/

ファイル名から最初の数字を抽出するにはどうすればよいですか?

これまでのところ、私はこれを持っています:

for i in DLG*-*-*-sprite.ogg; do echo "${i//[^0-9]}";done

しかし、最初の数字 (例: 23) だけが必要なのに、すべての数字 (例: 230001) が出力されます。

答え1

OS X を使用していると仮定していますが、OS X-tには のオプションがありませんmv。スクリプトが何千ものファイルを処理している場合、これは非常に遅くなります。

    for file in DLG*; do
    # Extract the three digits after DLG
    getnum=${file%%-*}
    getnum=${getnum#???}

    # make the directory dialogue### or exit if there is an error
    echo mkdir -p "dialogue${getnum}" || exit

    echo mv "$file" "dialogue${getnum}"
    done

出力が満足できるものであれば、echo前の部分を削除します。mkdirmv

答え2

次のようにして mv コマンドを生成できます。

for f in DLG*; do echo "$f" | sed 's/DLG\([0-9]\+\).*/mv "\0" "dialogue\1\/"/g'; done

コマンドは次のように出力されます:

mv "DLG023-00-01.prosody.json" "dialogue023/"
[...]
mv "DLG028-00-01.prosody.json" "dialogue028/"
[...]

それが望みどおりであれば、その出力をパイプするだけでbash実行されます。

for f in DLG*; do echo "$f" | sed 's/DLG\([0-9]\+\).*/mv "\0" "dialogue\1\/"/g'; done | bash

答え3

以下を使用した 1 行のソリューションfind:

find . -name DLG* -exec bash -c 'DEST=$(echo "$0" | sed -r "s/DLG([0-9]+)-.*/dialogue\1/"); mkdir "$DEST"; mv "$0" "$DEST"' {} \;
  • findDLG*コマンドはこのディレクトリからファイルを検索します。
  • 結果ごとにbash -c文を実行します。

次の文ではbash:

  • DEST=$(echo "$0" | sed -r "s/DLG([0-9]+)-.*/dialogue\1/");find( $0) からすべての結果を選択し、sed最初の-(DLG([0-9]+)-.*)の前のすべての数字dialogueを、その数字 ( dialogue\1) に置き換えて、 という変数に格納しますDEST
  • mkdir "$DEST"必要なフォルダーを作成します。
  • mv "$0" "$DEST"'ファイルをそのディレクトリに移動します。

答え4

いくつかのアイデア:

for i in DLG*-\*-\*-sprite.ogg; do echo "${i//[^0-9]}" | head -c 2; echo ;done

すべて同じ長さであることが確実な場合:

for i in DLG*-\*-\*-sprite.ogg; do echo "${i:3:3}" ;done

関連情報