Arquivos específicos do Linux (mv ou cp) de uma lista de arquivos de texto?

34

Eu tenho um diretório de muitos arquivos, algo como 50.000 pdf e outros arquivos em um servidor. Eu preciso mover os específicos para outro diretório. Posso gerar uma lista dos arquivos que precisam ser movidos em csv ou em qualquer outro formato de texto.

O que preciso fazer é executar um script bash e mover ou copiar os arquivos listados no arquivo de texto para outro diretório.

Existe uma maneira fácil de fazer isso? Todas as sugestões ou recursos serão muito apreciados.

Jestep
fonte
Além disso, os arquivos são nomeados aleatoriamente quando adicionados ao diretório. Não há convenção de nomenclatura ou lógica que possa ser usada para mover arquivos específicos.
Jestep

Respostas:

26

rsync tem várias opções que podem levar uma lista de arquivos para processo ( --files-from, --include-from, etc.).

Por exemplo, isso fará o truque:

rsync -a /source/directory --files-from=/full/path/to/listfile /destination/directory
Ignacio Vazquez-Abrams
fonte
2
exemplo:rsync -a /source/directory --files-from=/full/path/to/listfile /destination/directory
anneb
28

Para evitar um uso inútil de cat(e se você não usar rsync):

xargs -a file_list.txt mv -t /path/to/dest

Isso manipulará qualquer nome de arquivo válido, a menos que contenha uma nova linha, se os arquivos estiverem listados um por linha.

Pausado até novo aviso.
fonte
2
Uma desvantagem dessa abordagem é que, se os arquivos da lista contiverem nomes de caminhos (ou seja, não estão todos no mesmo diretório), o uso de mvtodos os arquivos será recolhido no mesmo diretório de destino. A rsyncabordagem na resposta aceita não sofre essa limitação.
Jason R
Além disso, eu tentei este comando e xargs iria quebrar em todos os arquivos que continham uma aspas simples ( "aspas simples inigualável")
James Beninger
Isso funcionou para mim porque eu realmente queria os arquivos de diferentes caminhos de origem no mesmo diretório de destino.
PseudoNoise
15
for file in `cat listoffiles`; do mv "$file" /path/of/destination ; done

assumindo o bash, além de listoffilesconter um arquivo por linha. Minha única objeção à rota rsync é que o OP solicita um método de mover os arquivos, sem copiá-los. O rsync tem mais bandeiras do que um casamento real, por isso tenho certeza de que pode ser modificado ainda mais, mas às vezes mais simples é melhor!

MadHatter apoia Monica
fonte
1
Essas soluções me parecem as mais flexíveis. Acabei usando-o com rsync em vez de cp ou mv apenas porque precisava da opção de caminhos de arquivo relativo.
Spamwich 06/08/2015
4
Nice, apenas tive problemas com espaços, então eu modificado para:while read -r file; do mv "$file" /path/of/destination ; done < listoffiles
user1182474
1
@ user1182474 Obrigado e um uso elegante do redirecionamento de entrada. O método tradicional de mostrar satisfação com uma resposta é votar, a propósito!
MadHatter apoia Monica
1
@ user1182474 obrigado por isso! O último passo em muitas modificações teve que ser feito às cegas para portar meus utilitários de backup OSX para o meu Android!
Charlie Gorichanaz 15/09/16
4

Isso depende do formato do arquivo de texto que você possui. Por exemplo, se você tiver a lista de arquivos gravados de forma que Cada arquivo esteja localizado em uma nova linha. Você pode usar xargs como:

$ cat your_text_file | xargs cp -t /path/to/destination

Além disso, você pode usar o findcomando com a -execopção copiar / mover os arquivos.

Khaled
fonte
3
rsync --files-from=file_list.txt /path/to/source/ /path/to/dest/

O Rsync tem o benefício adicional sobre os comandos cpou mvporque ele criará pastas automaticamente se elas não existirem.

Paul Wenzel
fonte
Por que é /path/to/sourcenecessário quando utiliza os caminhos da lista de arquivos?
bzero
@bzero talvez a lista de arquivos possa conter caminhos relativos?
DreadfulWeather
2

Eu acho que a resposta do rsync é melhor, mas apenas para outra opção:

tar -cf - -T FILE_OF_FILENAMES_TO_MOVE.txt |(cd /path/to/new/dir && tar -xvf -)
jj33
fonte
Isso é bom para um arquivo Dockerfile, pois o tar está disponível na imagem base do ubuntu, mas não no rsync.
kristianp
1

Eu acidentalmente copiei o conteúdo completo de um diretório em um diretório de destino em vez de mover o diretório completo. Isso resultou em um diretório de destino desordenado, em vez de o diretório de origem ser adicionado ao diretório.

Para corrigir isso, fiz o seguinte:

ls -rt /path/to/cluttered/destination/directory/ > /opt/dircheck/filestomove O comando acima cria o arquivo filestomove que será uma lista de todo o conteúdo do diretório de destino, classificado inversamente por tempo, significando do mais antigo para o mais recente.

Em seguida, criei um subdiretório do diretório de destino agora desordenado para mover o material.

mkdir /path/to/cluttered/destination/directory/newsubdirectory

Depois, repeti a listagem do diretório, exceto a listagem na tela e a exibição de mais detalhes.

ls -lrht /path/to/cluttered/destination/directory/ Esta linha lista o diretório, classificado por data crescente (classificação inversa por hora) e mostra mais informações, incluindo a data / hora de cada arquivo no diretório de destino agora desordenado. Refiro-me a isso, começando no topo para mostrar quais diretórios e arquivos eu quero manter onde eles estavam. Haverá uma lacuna no carimbo de data / hora dos arquivos em que todos os novos arquivos iniciam e que não deveriam estar lá.

Em seguida, editei o arquivo de gravação de arquivo criado na primeira etapa acima (que é classificada por data) e excluí alguns da lista que estavam lá anteriormente e quero permanecer no diretório original.

vim /opt/dircheck/filestomove Exclua da parte superior todos os arquivos que você não deseja mover.

Em seguida, usei o comando listado anteriormente nesta postagem para mover os arquivos da minha lista para o novo diretório que criei.

sudo xargs -a /opt/dircheck/filestomove mv -t /path/to/cluttered/destination/directory/newsubdirectory

Isso moveu todos os arquivos em uma fração de segundo. (Nota: você pode não precisar do sudo no início, isso é uma questão de permissões de arquivo).

Agora, meu diretório de destino original é agradável e limpo e contém um novo diretório com todos os arquivos e diretórios que o estavam atrapalhando.

John
fonte
1

Se (e somente se), você não possui caracteres desagradáveis ​​nos nomes de arquivos (espaços, novas linhas, o que confundiria xargs sobre como dividir as coisas em argumentos individuais) e gera uma lista de arquivos separados por novas linhas (um arquivo por linha), você poderia fazer algo assim.

cat filenames.txt | xargs mv -t /path/to/move/files/to

(Em geral, veja man xargs , é incrível)

Se o seu mv em particular não tiver a opção -t, você também poderá fazer alguns truques como

( cat filenames.txt; echo; echo /path/to/move/files/to ) | xargs mv

Nota - nenhum deles funcionará como esperado se houver nomes de arquivos com novas linhas.

Kjetil Joergensen
fonte
Contudo; Veja a resposta de Ignacio, o rsync é feito para esse tipo de coisa.
Kjetil Joergensen
cp, mve similares não têm -topção nos bsd 's, e o segundo exemplo com subshell não funcionou para mim ( /path/to/moveé anexado como o último nome do arquivo)
1
@ w17t - parece que os nomes de arquivo.txt não terminam com uma nova linha, adicione uma nova linha ao final de nomes de arquivo.txt ou faça algo como(cat filenames.txt; echo; echo /path/to/move/files/to) | xargs mv
Kjetil Joergensen 10/01
0

Tente algo como:

cat list.txt | while read line; do mv "$line" /images; done
AliGibbs
fonte
poderia ter sido while read line; do mv $line /images; done < list.txt como um único comando
ignora 17/09/15
0

O seguinte funcionou para mim, onde eu precisava copiar todos os arquivos PNG de um caminho específico (e todos os subdiretórios) para um novo local, preservando a estrutura de diretórios:

rsync -av --prune-empty-dirs --include='*/' --include='*.png' --exclude='*' source/ destination/

Como o RSYNC cria o espelho da estrutura de diretórios primeiro e depois sincroniza os arquivos, você pode acabar com pastas em excesso que estão vazias. Eu usei o sinalizador --prune-empty-dirs para remover esses diretórios vazios.

Não tenho afiliação, mas achei correto dar crédito à fonte que inspirou essa solução: http://techblog.zabuchy.net/2011/transfer-only-selected-file-types-with-rsync/

John Mark Mitchell
fonte