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

Но это выводит все цифры (например, 230001), когда мне нужна только первая (например, 23).

решение1

-tЯ предполагаю, что вы используете OS X, в которой нет такой возможности 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предыдущую версию mkdirи, mvесли результат вас удовлетворит, выполните следующие действия.

решение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

Однолинейное решение с использованием find:

find . -name DLG* -exec bash -c 'DEST=$(echo "$0" | sed -r "s/DLG([0-9]+)-.*/dialogue\1/"); mkdir "$DEST"; mv "$0" "$DEST"' {} \;
  • findкоманда ищет DLG*файлы в этом каталоге.
  • Для каждого результата приведите 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

Связанный контент