Movendo milhões de arquivos para um diretório diferente com padrões de nomes específicos

10

Eu tenho milhões de arquivos com a seguinte nomenclatura em uma máquina Linux:

1559704165_a1ac6f55fef555ee.jpg

Os 10 primeiros dígitos são de data e hora e os seguidos de a _são IDs específicos. Quero mover todos os arquivos correspondentes a IDs específicos de nome de arquivo para uma pasta diferente.

Eu tentei isso no diretório com arquivos

find . -maxdepth 1 -type f | ??????????_a1ac*.jpg |xargs mv -t "/home/ubuntu/ntest"

No entanto, estou recebendo um erro indicando:

bash 1559704165_a1ac6f55fef555ee.jpg: command not found

Quando tentei, mv ??????????_a1ac*.jpg estou recebendo um erro muito longo da lista de argumentos. Eu tenho pelo menos 15 padrões de nome de arquivo diferentes. Como eu os movo.

Damasco
fonte
1
O bash diz tudo: tenta executar esse nome de arquivo, pois é o primeiro da linha no 2º estágio do pipe (seu pipe de 2º estágio é | ??????????_a1ac*.jpg:: bash o expande para vários nomes de arquivo, o primeiro é 1559704165_a1ac6f55fef555ee.jpg, e você acaba , em que fase 2a tubo, tentando executar: 1559704165_a1ac6f55fef555ee.jpg next_matching_filename 3rd_matching_filename ... nth_matching_filenameEu acho que você tentou em vez disso. filtro para que filename (ver respostas abaixo para isso)
Olivier Dulac

Respostas:

15

Você deveria usar:

find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' \
-exec mv -t destination "{}" +

Isso maxdepth 1significa que você deseja procurar no diretório atual sem subdiretórios.

type f significa encontrar apenas arquivos.

name '??????????_a1ac*.jpg' é um padrão que corresponde ao arquivo que você está pesquisando.

mv -t destination "{}" +significa mover arquivos correspondentes para o destino. Aqui +adiciona novos arquivos correspondentes ao anterior, como:

mv -t dest a b c d

Aqui abcd existem arquivos diferentes.

Prvt_Yadav
fonte
Obrigado por responder de forma concisa a esta pergunta de pessoas. Em vez de simplesmente despejar uma solução, talvez você possa explicar como / o que / por quê. Em vez de ser útil para uma pessoa, uma vez, pode ser útil para todos, o tempo todo. A mesma pergunta foi feita e respondida inúmeras vezes nos últimos 40-50 anos. O problema é que nunca é explicado bem. Ensine um homem a pescar. Enquanto isso: gnu.org/software/findutils/manual/html_node/find_html/… e, como costuma ser o caso, a Wikipedia é mais útil do que os documentos oficiais: en.wikipedia.org/wiki/Find_ ( Unix)
vozes
Veja a resposta atualizada.
Prvt_Yadav 08/07/19
Observe que -té uma extensão GNU e, portanto, pode não estar disponível em outros tipos de derivativos UNIX.
Kevin
Quando você diz "Aspas duplas impedem a divisão de palavras". Presumo que você esteja se referindo "{}", nesse caso, quero ressaltar que {}não é expandido pelo shell e não precisa ser citado. O shell passa {}para encontrar e encontrar vê {}e o substitui por nomes de caminho. O Find Find não usa o analisador de shell e não faz sua própria divisão de palavras. A citação não causa nenhum dano, é apenas que a justificativa fornecida é um pouco imprecisa.
jw013 9/07/19
@ jw013 obrigado.
Prvt_Yadav
11

Seu comando,

find . -maxdepth 1 -type f | ??????????_a1ac*.jpg |xargs mv -t "/home/ubuntu/ntest"

Apresenta a lista de todos os arquivos para todos os arquivos!

find . -maxdepth 1 -type f -name `*_a1ac*.jpg` -print0 |\
xargs  -0 -r mv -t "/home/ubuntu/ntest"

fará o truque.

waltinator
fonte
1
muito obrigado ... sua solução trabalhado muito ... obrigado por me deixar saber onde eu errei
Apricot
8

Você está muito perto. Você deve usar a -nameopção para find. E lembre-se de citar o padrão.

assim

find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' |xargs mv -t "/home/ubuntu/ntest"
Stephen Harris
fonte
Muito obrigado ... a sua solução funcionou muito .... graças adicionais para deixar-me saber que eu estava perto da solução .... é um motivador para um novato como eu
Apricot
1
você deve adicionar a -print0como o último argumento à localização (em vez do padrão: -print) e adicionar a -0como a primeira opção ao xargs (por exemplo:) xargs -0 mv -t "/home/ubuntu/ntest". Dessa forma, todos os tipos de nomes de arquivos estranhos (com espaços, com "nova linha", etc.) podem ser manipulados. find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' -print0 |xargs -0 mv -t "/home/ubuntu/ntest" (funciona apenas com GNU-como achado, embora)
Olivier Dulac
2

Não é tão "bom" quanto as findsoluções, mas outra solução válida é tornar os mvcomandos mais granulares.

Isso faz 4096 movimentos, com um número menor de arquivos movidos por mvoperação.

FILEPAT=a1ac
for i in $(seq $((0x000)) $((0xfff))); 
do 
   H=$(printf '%x\n' $i)
   mv 1559704165_${FILEPAT}${H}*.jpg /home/ubuntu/ntest
done
RonJohn
fonte
Este é um truque inteligente para quem não tem find(por qualquer motivo).
forest
-1

Se você deseja mover arquivos no mesmo sistema host, o que eu acho que você está fazendo com o seu mv, rsyncpoderia ser uma opção mais rápida:

rsync -av --inplace -W /source/??????????_a1ac*.jpg /home/ubuntu/ntest/

--inplacee -Westão configurados para acelerar o processo.

Se isso gerar outro erro da lista de argumentos muito longo , você poderá alimentar listas pararsync

Faça a lista com find, por exemplo

find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' > /tmp/my_image_list.txt

e dê para rsync

rsync -av --inplace -W --files-from=/tmp/my_image_list.txt /path/to/files /home/ubuntu/ntest/

A fonte aqui é /path/to/files, porque rsynctratará a lista que você fornecer como relativa à sua fonte.


O ponto é: rsyncé mais rápido que mv, se os arquivos não estiverem no mesmo sistema de arquivos .

Robert Riedl
fonte
É provável que atingiu a mesma "lista de argumentos demasiado longo" Erro do OP mencionado
Grump
@Grump, para evitar isso, o OP poderia escrever a lista de arquivos a serem copiados para um arquivo, ou seja, find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' > /tmp/my_image_list.txte depois passá-la para o rsync --files-from=/tmp/my_image_list.txt. O ponto é que rsyncé mais rápido. A menos que os arquivos residam no mesmo sistema de arquivos, que o OP não indicou.
Robert Riedl
@RobertRiedl: você deve editar sua resposta e adicionar essas informações. Os comentários podem ser impermanentes.
10119 NickD
@ NickD, eu atualizei minha resposta.
Robert Riedl