Come posso spostare ricorsivamente tutti i file nelle sottodirectory in una singola directory?


10

Sto cercando di raccogliere tutti i file nella directory corrente e tutte le sottodirectory in una directory. Sto provando qualcosa di simile al seguente

find -type f -exec mv {} collection/{} \; 

il comando sopra non funzionerà perché il secondo {}fornisce il percorso completo, come posso raccogliere tutti i file?

Risposte:


14

Rimuovi {}da mv, mvlo prenderà come directory di destinazione ignorando tutte le directory principali:

find -type f -exec mv {} collection/ \;

ohh non mi è venuto in mente. grazie :)
Bunny Rabbit

Come ho detto nella mia risposta alla domanda, questa è potenzialmente una cattiva idea. Forse usare l'argomento -maxdepth 1sarebbe di aiuto.
loevborg

Vieni a pensarci bene, sembra che io abbia letto la tua domanda in modo sbagliato :) Scusa.
loevborg,

@loevborg: ho aggiunto "ricorsivamente" al titolo ora. Se c'è ancora confusione, si prega di modificarlo e migliorarlo :)
Lekensteyn

1
una variazione più veloce di questa risposta èfind -type f -print0|xargs -0r mv -it colection/
hildred

5

Invece di usare find(il che fa bene il lavoro), puoi anche usare la shell a tal fine.

Supponiamo che tu voglia tutti i file da $ PWD a $ DEST. Il tentativo naturale sarebbe:

mv $PWD/* $DEST

Come funziona? L'espressione "$ PWD / *" si espande nei nomi di tutti i file in quella directory. Questa funzione di shell si chiama "globbing". L'ultimo argomento di mvè la directory di destinazione. Se hai molti file, questo non funzionerà perché la lunghezza della riga di comando è limitata.

Ma la soluzione ha il problema di omettere file dot - o file "nascosti", file e directory il cui nome inizia con un ".". Per risolvere questo problema, devi dire alla tua shell di includere dotfile durante il globbing. Per fare questo, usa

shopt -s dotglob

quando si utilizza bash(e probabilmente si utilizza a bashmeno che non sia stata modificata l'impostazione predefinita). In questa shell, il comando sopra funzionerà anche per i dotfile.

A parte questo, zshhai la possibilità di scegliere questo caso per caso. Per fare questo, metti

setopt extendedglob

nel tuo .zshrc. Quindi puoi usare

mv $PWD/*(D) $DEST

per spostare tutti i file, inclusi i dotfile. (La "D" ha l'effetto di abilitare temporaneamente l'opzione "GLOB_DOTS").

Ora la domanda originale era spostare tutti i file regolari (non le directory) da tutte le sottodirectory e le loro sottodirectory in una singola directory. Questo può essere realizzato con zsh:

mv $PWD/**/*(D.)

Qui l'espressione **/*fa scendere globalmente ricorsivamente nelle sottodirectory. Il Dmezzo "seleziona anche dotfile"; il .mezzo "seleziona solo file regolari, non directory".


beh, anch'io volevo ricorrere a tutte le sottodirectory, ma grazie al fatto che le informazioni sono utili, ci si imbatte in troppe volte questa situazione :)
Bunny Rabbit

In realtà, find non è eccessivo per questo, globbing selezionerà tutte le partite, non solo i file, ma anche le directory. Se stai preoccupazioni per le prestazioni, si potrebbe anche usare qualcosa come: find -type f -exec mv -t collection/ {} +. Consulta la pagina di manuale su come funziona.
Lekensteyn,

Lekensteyn, hai ragione. Ho aggiornato la risposta ora che ho capito la domanda.
loevborg,

2
Risposta meravigliosa, peccato che non sia particolarmente rilevante per la domanda :).
crazy2be
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.