Sposta tutti i file con una determinata estensione da più sottodirectory in una directory


43

Ho un sacco di file .zip in diverse directory:

Fol1/Fol2
Fol3
Fol4/Fol5

Come potrei spostarli tutti in una cartella base comune?


Vuoi mantenere la struttura delle directory? Vuoi spostare le directory o solo i file zip?
Giordania,

Voglio solo spostare i file zip. Non mi importa davvero delle directory: possono essere lasciate sole o cancellate.
InquilineKea

Risposte:


55

Vai alla directory di livello superiore dell'albero contenente i file zip ( cd …), quindi esegui

mv **/*.zip /path/to/single/target/directory

Questo funziona fuori dagli schemi in zsh. Se la tua shell è bash, dovrai shopt -s globstarprima eseguire (puoi e dovresti inserire questo comando nel tuo ~/.bashrc). Se la tua shell è ksh, dovrai set -o globstarprima eseguirla (mettila nella tua ~/.kshrc).

In alternativa, utilizzare find, che funziona ovunque senza una preparazione speciale ma è più complicato:

find . -name '*.zip' -exec mv {} /path/to/single/target/directory \;

Se si desidera rimuovere in seguito directory vuote, in zsh:

rmdir **/*(/^Fod)

In bash o ksh:

rmdir **/*/

e ripetere finché ci sono directory vuote da rimuovere. In alternativa, in qualsiasi shell

find . -depth -type d -empty -exec rmdir {} \;

Il primo findcomando sopra ha funzionato in bash, ma ha dovuto cambiare in find . -nameetc per farlo funzionare.
JeffThompson,

1
@Jeff .è implicito per GNU find ma non per altri, l'ho aggiunto esplicitamente.
Gilles 'SO- smetti di essere malvagio'

13

Se vuoi solo spostare i .zipfile, potresti fare qualcosa del genere

mkdir ./zipfiles
find . -name "*.zip" -exec mv "{}" ./zipfiles \;

3

Se stai usando bash versione 4 o successiva o zsh puoi anche usare globbing ricorsivo:

mv **/*.zip /path/to/move/zip/files/to

Questo sposterà SOLO i file e non i relativi percorsi, quindi potrebbero verificarsi collisioni.


cosa intendi per percorsi relativi?
Kunok,

2

Questo è sicuro quando si spostano dati ed è privo di errori che supportava soprattutto la distribuzione indipendentemente dalle versioni. Questo comando esegue la scansione delle sottodirectory e quindi si sposta o copia nella nuova directory di destinazione.

find . -name *.flac -exec mv '{}' "./flac/" ";"
  • Esegui questo comando nella directory principale che contiene sottodirectory con i file che desideri spostare.
  • Dove puoi cambiare *.flacqualcosa come *.zipnel tuo caso. O *.docqualsiasi estensione funziona.
  • ed mvè il comando per spostare i file, oppure è possibile utilizzare cpper copiare i dati invece di spostarli.
  • ./flac/è la directory di destinazione in cui voglio spostare tutti i file FLAC. Puoi anche dargli un percorso completo come/home/myid/flac/

Esempio completo (in questo caso, ci sono molte sottodirectory con il nome dell'artista musicale a /home/myid/Music/e quindi i file FLAC sono tutti su livelli di sottodirectory diversi. Dato che non ho bisogno di cartelle per artisti ma voglio avere tutti i file FLAC in una directory in/home/myid/Music/flac/

cd /home/myid/Music
mkdir flac
find . -name *.flac -exec mv '{}' "./flac/" ";"
cd flac
ls

Quindi visualizzerà tutti i file FLAC.


ciò che ;fare?
Francesco Boi,

@FrancescoBoi assicurati di attendere fino a quando il comando bash nella stessa riga termina il suo lavoro. e poi passa alla riga successiva di comandi bash. Questo è utile per comandi che contengono script come .pl o python perché bash lo eseguirà e poi salterà alla riga successiva, quindi per sicurezza, io uso; dopo i comandi che richiedono tempo o script, nel caso bash lo salti.
Seandex,

0

Come hack bash, puoi usare il potere di tar:

(cd origin/;find . -exec file --mime-type "{}" \;|grep "application/zip"|cut -d ':' -f 1|xargs tar cf -)|(cd target/; tar xf -) && rm -fr origin/

Ciò ha il vantaggio di non dipendere dalle estensioni dei file, poiché utilizza il filecomando per scegliere i file da spostare e preserva la struttura della directory, ma non funziona con percorsi contenenti spazi.

Il finale rmè lì solo per rimuovere i file originali (perché @InquilineKea ha detto che non gli importa della cartella originale nel commento).

Naturalmente questo è particolarmente adatto se le cartelle origin / e target / si trovano su dischi diversi. Altrimenti le altre soluzioni proposte sono più efficienti (anche se si basano su convenzioni di denominazione, anziché sul filecontenuto).


0

Supponendo che tu abbia le versioni GNU di find e mv, le seguenti saranno più efficienti delle risposte basate su find esistenti:

find . -name '*.zip' -exec mv --target-directory='/path/to/outputdir' '{}' +

L'uso di +a alla fine di find -exec significa che un elenco di file verrà passato al comando mv, anziché eseguire un comando mv per file trovato. Tuttavia, una limitazione di ciò è che puoi solo posizionare '{}' alla fine del comando, il che richiede l'uso dell'opzione mv --target-directory, e per quanto ne so che è un GNU-ism.

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.