bash extrai o primeiro número do nome do arquivo

bash extrai o primeiro número do nome do arquivo

Estou tentando mover arquivos assim:

...
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
...

em suas respectivas pastas, por exemplo: mova o arquivo para dialogue023/quando ele começa com DLG023; até dialogue024/quando começa com DLG024; e assim por diante.

Todos os arquivos e diretórios estão no mesmo nível.

Em outras palavras, estou tentando produzir comandos como este:

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

Como posso extrair o primeiro número do nome do arquivo?

Até agora eu tenho isso:

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

Mas isso gera todos os dígitos (por exemplo: 230001) quando eu quero apenas o primeiro (por exemplo: 23).

Responder1

Presumo que você esteja usando o OS X, que não tem a -topção no mv. Isso será dolorosamente lento se o script estiver processando milhares de arquivos.

    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

Retire o echoantes mkdire mvse a saída for satisfatória.

Responder2

Você poderia gerar o comando mv usando isto:

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

Agora, o comando é impresso assim:

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

Se for o que você deseja, basta canalizar essa saída bashe ela será executada:

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

Responder3

Solução de uma linha usando find:

find . -name DLG* -exec bash -c 'DEST=$(echo "$0" | sed -r "s/DLG([0-9]+)-.*/dialogue\1/"); mkdir "$DEST"; mv "$0" "$DEST"' {} \;
  • findcomando procure por DLG*arquivos deste diretório.
  • Para cada resultado execute a bash -cfrase.

Na bashfrase:

  • DEST=$(echo "$0" | sed -r "s/DLG([0-9]+)-.*/dialogue\1/");escolhe todos os resultados de find ( $0) e usando sedsubstitui todos os números antes do primeiro -(DLG([0-9]+)-.*) pelos dialogueseguintes com esses números ( dialogue\1) e coloca em uma variável chamada DEST.
  • mkdir "$DEST"cria a pasta necessária.
  • mv "$0" "$DEST"'move o arquivo para esse diretório.

Responder4

Algumas ideias:

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

Se você tem certeza de que todos têm o mesmo comprimento:

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

informação relacionada