coloque milhares de arquivos, em pastas com nomes específicos

coloque milhares de arquivos, em pastas com nomes específicos

eu tenho uma pasta chamada test, que contém apenas arquivos JPEG. Milhares de arquivos. preciso colocar esses milhares de arquivos, nomeados como 1.jpg, 2.jpg... 345623.jpg, em subpastas que terão nomes como 001000, 002000, cada uma contendo 1.000 arquivos. Portanto, preciso mover todos os arquivos jpg da pasta de teste para subpastas que contenham cada 1000 arquivos jpg, da maneira mais eficiente e com melhor desempenho.

O que tenho até agora é:

i=1;while read l;do mkdir $i;mv $l $((i++));done< <(ls|xargs -n1000)

Responder1

find . -type f \
| split -l 1000 -a 3 --numeric-suffixes=1 \
  --filter='target="${FILE}000"; mkdir "$target" && xargs -d "\n" mv -t "$target"' \
  - ''

Explicação:

  • find . -type fencontra arquivos (também em subdiretórios, mas acredito que no seu caso ainda não existam subdiretórios).
  • split -l 1000 -a 3 --numeric-suffixes=1 ... - ''lê seu stdin ( -) e divide os dados em pedaços, cada pedaço com 1.000 linhas ( -l 1000). Para cada pedaço é associado um "nome" que consiste no prefixo vazio ( '') e no sufixo numérico começando em 1 ( --numeric-suffixes=1) do comprimento 3 ( -a 3). Com efeito, neste ponto, os nomes são 001, 002e assim por diante.
  • --filter=...executa o comando especificado separadamente para cada pedaço, o respectivo nome está disponível como $FILE. O comando para executar é

    target="${FILE}000"; mkdir "$target" && xargs -d "\n" mv -t "$target"
    
    • target="${FILE}000"converte o nome como 001ou 002para o nome de diretório futuro que você deseja ( 001000ou 002000etc.) e armazena isso na targetvariável.
    • mkdir "$target"cria um novo diretório com o nome desejado.
    • xargs -d "\n" ...lê o pedaço inteiro (1000 caminhos de arquivo ou menos no último pedaço) e usa cada linha inteira (nova linha como delimitador: -d "\n") como argumento para o comando a seguir.
      • mv -t "$target"move objetos (passados ​​por xargs) para o diretório recém-criado.

Notas:

  • O comando não se importa com nomes de arquivos. 345623.jpgnão necessariamente terminará em 346000/. Razões possíveis:
    • findnão classifica; mas mesmo se você colocar sort -nentre finde split, pode ser...
    • existem lacunas na numeração. splitaceitará 1.000 entradas, não importa o que aconteça (a menos que seja o último pedaço; se for o caso, então 1.000 ou menos).
  • mkdir ... && xargs ...não será executado xargsse mkdirfalhar (cuidado com os diretórios existentes).
  • Use cp -l -t "$target"em vez de mv -t "$target"para criar hardlinks em diretórios, deixando intactas as entradas já existentes no diretório atual. Dessa forma, caso algo dê errado, basta acessar rm -ros diretórios e começar de novo. Com mv, se a tarefa for interrompida, você acabará com alguns arquivos movidos, outros não; isso pode ser uma bagunça.
  • Acho que -a 3você não vai conseguir passar 999( 999000depois de acrescentar zeros à direita). Se splitprecisar criar mais pedaços, ele falhará no meio do trabalho. Por esse motivo, certifique-se de 999que é suficiente antes de executar o comando.
  • Nomes com novas linhas quebrarão o código (em geral, os nomes dos arquivos parecem bons).

informação relacionada