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 f
encontra 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ão001
,002
e 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 como001
ou002
para o nome de diretório futuro que você deseja (001000
ou002000
etc.) e armazena isso natarget
variá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 porxargs
) para o diretório recém-criado.
Notas:
- O comando não se importa com nomes de arquivos.
345623.jpg
não necessariamente terminará em346000/
. Razões possíveis:find
não classifica; mas mesmo se você colocarsort -n
entrefind
esplit
, pode ser...- existem lacunas na numeração.
split
aceitará 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á executadoxargs
semkdir
falhar (cuidado com os diretórios existentes).- Use
cp -l -t "$target"
em vez demv -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 acessarrm -r
os diretórios e começar de novo. Commv
, se a tarefa for interrompida, você acabará com alguns arquivos movidos, outros não; isso pode ser uma bagunça. - Acho que
-a 3
você não vai conseguir passar999
(999000
depois de acrescentar zeros à direita). Sesplit
precisar criar mais pedaços, ele falhará no meio do trabalho. Por esse motivo, certifique-se de999
que é suficiente antes de executar o comando. - Nomes com novas linhas quebrarão o código (em geral, os nomes dos arquivos parecem bons).