Como posso mover vários arquivos com nomes diferentes usando mv em loop?

Como posso mover vários arquivos com nomes diferentes usando mv em loop?

Tenho 2.500 arquivos chamados LposK.dat com L variando de 1 a 10 e K variando de 0,00 a 49,80. Preciso mover aqueles que possuem o mesmo K para uma pasta. Eu consigo fazer isso usando:

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

Mas tenho que alterar manualmente o valor de K e repeti-lo várias vezes. Eu queria saber se existe alguma maneira de usar o índice de um loop (por exemplo: for loop) dentro dos comandos find e mv para que eu possa escrever um script para fazer isso.

Responder1

Para obter Kfrom LposK.dat, se essa string estiver em $name, podemos fazer

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

Isso funcionaria mesmo se $namefosse um nome de caminho como some/path/LposK.dat(e mesmo se some/pathcontivesse a string pos), o que é útil quando o conectarmos posteriormente ao find.

Para mover um arquivo:

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

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

Com 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 {} +

Isso daria ao sh -cscript interno vários nomes de caminhos como argumentos, e o script iteraria sobre eles, movendo cada um para o subdiretório correto de $HOME/destination.

Relacionado:


Se seus arquivos estiverem em um único subdiretório (o diretório atual), você poderá fazer isso ainda mais facilmente sem 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

informação relacionada