File specifici di Linux (mv o cp) da un elenco di file di testo?


34

Ho una directory di molti file, qualcosa come 50.000 pdf e altri file su un server. Ho bisogno di spostare quelli specifici in un'altra directory. Posso generare un elenco dei file che devono essere spostati in CSV o in qualsiasi altro formato di testo.

Quello che devo fare è eseguire uno script bash e spostare o copiare i file elencati nel file di testo in un'altra directory.

C'è un modo semplice per farlo? Eventuali suggerimenti o risorse sarebbero molto apprezzati.


Inoltre, i file vengono denominati in modo casuale quando vengono aggiunti alla directory. Non esiste una convenzione di denominazione o alcuna logica che possa essere utilizzata per spostare file specifici.
Jestep,

Risposte:


26

rsync ha diverse opzioni che possono prendere un elenco di file da elaborare ( --files-from, --include-from, ecc).

Ad esempio, questo farà il trucco:

rsync -a /source/directory --files-from=/full/path/to/listfile /destination/directory

2
esempio:rsync -a /source/directory --files-from=/full/path/to/listfile /destination/directory
anneb

28

Per evitare un uso inutile di cat(e se non lo usi rsync):

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

Questo gestirà qualsiasi nome di file valido, a meno che non contenga una nuova riga, se i file sono elencati uno per riga.


2
Uno svantaggio di questo approccio è che se i file nell'elenco contengono nomi di percorso (ovvero non sono tutti nella stessa directory), l'uso di mvli comprime tutti nella stessa directory di destinazione. L' rsyncapproccio nella risposta accettata non soffre di questa limitazione.
Jason R,

Inoltre, ho provato questo comando e xargs si sarebbe interrotto su tutti i file che contenevano una singola citazione ("virgoletta singola senza pari")
James Beninger,

Questo ha funzionato per me perché in realtà volevo i file da percorsi di origine diversi nella stessa directory di destinazione.
PseudoNoise,

15
for file in `cat listoffiles`; do mv "$file" /path/of/destination ; done

supponendo bash, oltre a listoffilescontenere un file per riga. La mia unica obiezione alla rotta rsync è che l'OP richiede un metodo per spostare i file, non copiarli. rsync ha più bandiere di un matrimonio reale, quindi sono sicuro che può essere ulteriormente modificato per farlo, ma a volte più semplice è meglio!


1
Questa soluzione mi sembra la più flessibile. Ho finito per usarlo con rsync invece di cp o mv solo perché avevo bisogno dell'opzione relativa ai percorsi dei file.
Spamwich,

4
Bene, ho appena avuto problemi con gli spazi, quindi l'ho modificato in:while read -r file; do mv "$file" /path/of/destination ; done < listoffiles
user1182474

1
@ user1182474 Grazie e un uso elegante del reindirizzamento dell'input. A proposito, il metodo tradizionale di mostrare soddisfazione per una risposta è di votare!
MadHatter supporta Monica il

1
@utente1182474 grazie per quello! l'ultimo passaggio di molte modifiche ha dovuto fare un po 'alla cieca il porting delle mie utility di backup OSX sul mio Android!
Charlie Gorichanaz,

4

Questo dipende dal formato del file di testo che hai. Ad esempio, se l'elenco dei file è scritto in modo tale che ogni file si trovi su una nuova riga. Puoi usare xargs come:

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

Inoltre, è possibile utilizzare il findcomando con l' -execopzione. per copiare / spostare i file.


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

Rsync ha l'ulteriore vantaggio rispetto ai comandi cpo mvperché creerà automaticamente cartelle se non esistono.


Perché è /path/to/sourcenecessario quando prende i percorsi dall'elenco dei file?
zero il

@bzero forse l'elenco dei file può contenere percorsi relativi?
DreadfulWeather, il

2

Penso che la risposta rsync sia migliore, ma solo per un'altra opzione:

tar -cf - -T FILE_OF_FILENAMES_TO_MOVE.txt |(cd /path/to/new/dir && tar -xvf -)

Questo è utile per un file Docker, poiché tar è disponibile nell'immagine di base di Ubuntu, ma non rsync.
kristianp,

1

Ho copiato accidentalmente l'intero contenuto di una directory in una directory di destinazione invece di spostare l'intera directory. Ciò ha comportato una directory di destinazione ingombra anziché la directory di origine aggiunta alla directory.

Per risolvere questo problema, ho fatto quanto segue:

ls -rt /path/to/cluttered/destination/directory/ > /opt/dircheck/filestomove Il comando sopra crea il file filestomove che sarà un elenco di tutti i contenuti della directory di destinazione, in ordine inverso in base al tempo, dal più vecchio al più recente.

Quindi ho creato una sottodirectory della directory di destinazione ora ingombra per spostare le cose in.

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

Quindi ho ripetuto l'elenco di directory, tranne l'elenco per lo schermo e mostrando più dettagli.

ls -lrht /path/to/cluttered/destination/directory/ Questa riga elenca la directory, ordinata per data crescente (ordinamento inverso per ora) e mostra ulteriori informazioni, incluso il timestamp data / ora di ciascun file nella directory di destinazione ora disordinata. Mi riferisco a questo, partendo dall'alto per mostrare quali directory e file voglio mantenere dove fossero. Ci sarà una lacuna nella data / ora dei file in cui iniziano tutti i nuovi file che non dovrebbero essere lì.

Quindi ho modificato il file filestomove creato nel primo passaggio sopra (che è ordinato per data) e cancellato i pochi dall'elenco che erano lì in precedenza che voglio rimanere dalla directory originale.

vim /opt/dircheck/filestomove Elimina dall'alto, tutti i file che non vuoi spostare.

Quindi ho usato il comando elencato in precedenza in questo post per spostare i file nel mio elenco nella nuova directory che ho creato.

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

Ciò ha spostato tutti i file in una frazione di secondo. (Nota: all'inizio potrebbe non essere necessario il sudo, si tratta di autorizzazioni per i file).

Ora la mia directory di destinazione originale è bella e pulita e contiene una nuova directory con tutti i file e le directory che la ingombravano.


1

Se (e solo se), non hai caratteri cattivi nei nomi dei file (spazi, newline, che confonderebbero xargs su come spezzare le cose in singoli argomenti) e generi un elenco di file separati da newline (un file per riga), potresti fare qualcosa del genere.

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

(In generale, vedi man xargs , è fantastico)

Se il tuo particolare mv non ha l'opzione -t, potresti anche fare qualche trucco

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

Nota: nessuno di questi funzionerà come previsto se ci sono nomi di file con nuove righe al loro interno.


Tuttavia; vedi la risposta di Ignacio, rsync è fatto per questo genere di cose.
Kjetil Joergensen,

cp, mvE simili non hanno -tun'opzione su BSD 's, e il secondo esempio con subshell non ha funzionato per me ( /path/to/moveviene aggiunto come l'ultimo nome del file)

1
@ w17t - sembra che filenames.txt non finisca con una nuova riga, o aggiungi newline alla fine di filenames.txt o faccia qualcosa del genere(cat filenames.txt; echo; echo /path/to/move/files/to) | xargs mv
Kjetil Joergensen,

0

Prova qualcosa del tipo:

cat list.txt | while read line; do mv "$line" /images; done

avrebbe potuto essere while read line; do mv $line /images; done < list.txt un singolo comando
ignivs

0

Quanto segue ha funzionato per me dove dovevo copiare tutti i file PNG da un percorso specifico (e tutti i sottodir) in una nuova posizione preservando la struttura delle directory:

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

Poiché RSYNC crea prima il mirror della struttura delle directory, quindi sincronizza i file, è possibile finire con cartelle in eccesso vuote. Ho usato il flag --prune-empty-dirs per rimuovere queste directory vuote.

Non ho affiliazioni, ma ho ritenuto giusto dare credito alla fonte che ha ispirato questa soluzione: http://techblog.zabuchy.net/2011/transfer-only-selected-file-types-with-rsync/

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.