¿Cómo puedo mover varios archivos con diferentes nombres usando mv en un bucle?

¿Cómo puedo mover varios archivos con diferentes nombres usando mv en un bucle?

Tengo 2500 archivos con el nombre LposK.dat con L que va de 1 a 10 y K que va de 0,00 a 49,80. Necesito mover los que tienen la misma K a una carpeta. Me las arreglo para hacer esto usando:

find . -name '*posK.dat' -exec mv {} ~/destination/K \;

Pero tengo que cambiar manualmente el valor de K y repetirlo varias veces. Me preguntaba si hay alguna forma de utilizar el índice de un bucle (por ejemplo, bucle for) dentro de los comandos find y mv para poder escribir un script para hacerlo.

Respuesta1

Para obtener Kfrom LposK.dat, si esa cadena está en $name, podemos hacer

k=${name%.dat}  # remove ".dat" suffix
k=${k##*pos}    # remove everything up to end of (the last) "pos"

Esto funcionaría incluso si $namefuera un nombre de ruta como some/path/LposK.dat(e incluso si some/pathcontuviera la cadena pos), lo cual es útil cuando luego lo conectamos a find.

Para mover un archivo:

k=${name%.dat}
k=${k##*pos}

dest="$HOME/destination/$k"
mkdir -p "$dest" && mv "$name" "$dest"  # only move if mkdir did not fail

Con find:

find . -type f -name '*pos*.dat' -exec sh -c '
    for name do
        k=${name%.dat}
        k=${k##*pos}

        dest="$HOME/destination/$k"
        mkdir -p "$dest" && mv "$name" "$dest"
    done' sh {} +

Esto le daría al sh -cscript interno una cantidad de nombres de rutas como argumentos, y el script los iteraría, moviendo cada uno al subdirectorio correcto de $HOME/destination.

Relacionado:


Si sus archivos están en un único subdirectorio (el directorio actual), puede hacerlo aún más fácilmente sin find:

for name in ./*pos*.dat; do
    [ ! -f "$name" ] && continue  # skip non-regular files

    k=${name%.dat}
    k=${k##*pos}

    dest="$HOME/destination/$k"
    mkdir -p "$dest" && mv "$name" "$dest"
done

información relacionada