bash extrae el primer número del nombre del archivo

bash extrae el primer número del nombre del archivo

Estoy intentando mover archivos como este:

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

en sus respectivas carpetas, por ejemplo: mueva el archivo a dialogue023/cuando comience con DLG023; hasta dialogue024/cuando comienza con DLG024; etcétera.

Todos los archivos y directorios están al mismo nivel.

En otras palabras, estoy intentando generar comandos como este:

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

¿Cómo puedo extraer el primer número del nombre del archivo?

Hasta ahora tengo esto:

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

Pero esto genera todos los dígitos (por ejemplo: 230001) cuando solo quiero el primero (por ejemplo: 23).

Respuesta1

Supongo que estás usando OS X, que no tiene la -topción en mv. Esto será tremendamente lento si el script procesa miles de archivos.

    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 el echoantes mkdiry mvsi el resultado es satisfactorio.

Respuesta2

Podrías generar el comando mv usando esto:

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

Ahora, el comando se imprime así:

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

Si es lo que desea, simplemente canalice esa salida bashy se ejecutará:

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

Respuesta3

Solución de una línea usando find:

find . -name DLG* -exec bash -c 'DEST=$(echo "$0" | sed -r "s/DLG([0-9]+)-.*/dialogue\1/"); mkdir "$DEST"; mv "$0" "$DEST"' {} \;
  • findEl comando busca DLG*archivos de este directorio.
  • Por cada resultado ejecuta la bash -csentencia.

En la bashfrase:

  • DEST=$(echo "$0" | sed -r "s/DLG([0-9]+)-.*/dialogue\1/");selecciona cada resultado de buscar ( $0) y usa sedreemplazar todos los números antes del primero -(DLG([0-9]+)-.*) con dialoguelos siguientes con esos números ( dialogue\1) e ingresa una variable llamada DEST.
  • mkdir "$DEST"crea la carpeta requerida.
  • mv "$0" "$DEST"'mueve el archivo a ese directorio.

Respuesta4

Un par de ideas:

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

Si estás seguro de que todos tienen la misma longitud:

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

información relacionada