Copia il tipo di file specifico mantenendo la struttura delle cartelle
Su Febbraio 10, 2021 da adminHo una struttura di cartelle con un mucchio di file * .csv sparsi nelle cartelle. Ora voglio copiare tutti i file * .csv in unaltra destinazione mantenendo la struttura delle cartelle.
Funziona in questo modo:
cp --parents *.csv /target cp --parents */*.csv" /target cp --parents */*/*.csv /target cp --parents */*/*/*.csv /target ...
e così via, ma vorrei farlo utilizzando un comando.
Risposta
find
ha unopzione -exec
molto utile:
find . -name "*.csv" -exec cp --parents \{\} /target \;
Commenti
- Probabilmente per questo motivo \ {\} \;
-
'{}'
funziona altrettanto bene - Anche se
-execdir
è più sicuro di-exec
, la semplice sostituzione di una con laltra non preserva la struttura delle cartelle come previsto. - Perché io ricevi il messaggio ‘ Ometti directory ‘ quando provo a copiarli con il tuo comando?
- Puoi spiegare perché il le parentesi graffe devono essere precedute da caratteri di escape qui?
Risposta
Puoi anche usare rsync
per questo.
$ rsync -a --prune-empty-dirs --include "*/" --include "*.csv" --exclude "*" source/ target/
Se desideri mantenere le directory vuote dallalbero dei sorgenti, ignora lopzione --prune-empty-dirs
:
$ rsync -a --include "*/" --include "*.csv" --exclude "*" source/ target/
Se non vuoi preservare link simbolici, date di modifica, permessi dei file, proprietari ecc., sostituisci -a
con unaltra combinazione di -rlptgoD
. 😉
Commenti
Risposta
Puoi utilizzare find e cpio in modalità pass-through
find . -name "*.csv" | cpio -pdm /target
Questo troverà tutti i file .csv nella directory corrente e sotto e copiarli in / target mantenendo la struttura della directory radicata in .
.
Se utilizzi
find /path/to/files -name "*.csv" | cpio -pdm /target
troverà tutti i file in /path/to/files
e sotto e li copierà in /target/path/to/files
e sotto .
Commenti
- Ho provato tutte le risposte dallalto verso il basso fino a questa, e questa è stata lunica che ha funzionato al primo tentativo
- Questa dovrebbe essere la risposta accettata.
- Ho trovato utili i documenti GNU : ” In modalità copy-pass, [richiesto dallopzione
-p
, cpio] legge lelenco dei file da copiare dallo standard input; la directory in cui verranno copiati viene fornita come argomento non opzionale. ” … ” -d Crea directory iniziali dove necessario. ” … ” -m Conserva i tempi di modifica dei file precedenti durante la creazione di file. ”
Risposta
Il comando cp
consente più argomenti di origine:
cp **/*.csv --parents ../target
CAVEAT: Sto usando un glob ricorsivo qui; questa è lopzione globstar
in Bash 4+ e ksh
ed è supportato per impostazione predefinita in zsh
. I glob ricorsivi non corrisponde a file e cartelle nascosti e alcune implementazioni seguono collegamenti simbolici mentre altre no .
Se la tua shell non lo fa ” t supp o glob ricorsivi, o se preferisci non usarli, puoi fare quanto segue:
-
*.csv */*.csv */*/*.csv */*/*/*.csv
– questo è ovviamente molto ridondante e richiede la conoscenza della profondità della struttura della directory. -
$(find . -name "*.csv")
– Questo corrisponde a cartelle e file nascosti.find
supporta anche la specifica se vengono seguiti o meno collegamenti simbolici, il che può essere utile.
Commenti
- questo è esattamente quello che ho provato (il glob ricorsivo) e ne ha trovati alcuni ma non tutti? abbastanza strano. Ho ottenuto lo stesso risultato esatto usando lo script npm copyfiles ma se uso il comando find trova tutto …
- @Randyaa I ‘ ne avrò bisogno maggiori dettagli su quali file, esattamente, non sono stati ‘ trovati per aiutarti. Puoi trovare la discussione qui e continuata qui sul comportamento preciso del glob ricorsivo utile .
- risulta che glob ricorsivo non era ‘ abilitato per qualche motivo …’ non mi sono mai imbattuto in questo problema prima, ma lho corretto con una semplice esecuzione di
shopt -s globstar
immediatamente prima del mio comando e tutto va bene. Grazie per il follow-up! -
--parents
era quello che stavo cercando. grazie
Risposta
Questo ha funzionato per me:
find -name "*.csv" | xargs cp --parents -t /target
Commenti
- Migliore risposta con la sintassi più semplice. Funziona bene ed è facile da ricordare. In molti casi
find [things] | xargs [do stuff]
è molto potente. - Daccordo. Molto semplice rispetto ad alcune delle altre risposte.
- Interruzioni se hai spazi nei nomi dei file
- @MichelePiccolini Gli spazi nei nomi dei file possono essere gestiti con
find -print0
exargs -0
.
Risposta
Da rsync
“s manpage:
-R, –relative
Usa percorsi relativi. Ciò significa che i nomi di percorso completi specificati sulla riga di comando vengono inviati al server anziché solo le ultime parti dei nomi di file. Ciò è particolarmente utile quando si desidera inviare più directory diverse contemporaneamente. Ad esempio, se si utilizza questo comando:
rsync -av /foo/bar/baz.c remote:/tmp/
… questo creerebbe un file chiamato baz.c in / tmp / sulla macchina remota. Se invece usassi
rsync -avR /foo/bar/baz.c remote:/tmp/
verrà creato un file denominato /tmp/foo/bar/baz.c sulla macchina remota, preservandone il percorso completo. Questi elementi di percorso aggiuntivi sono chiamati ” impli directory ed “(es. le directory “foo” e “foo / bar” nellesempio precedente).
Quindi, anche questo funzionerebbe:
rsync -armR --include="*/" --include="*.csv" --exclude="*" /full/path/to/source/file(s) destination/
Commenti
- Grazie per aver fornito questa risposta. Compatibile con i percorsi BSD userland (macOS), e con spazi.
Risposta
Supponendo che desideri replicare questa struttura da ./source
a ./destination
:
cd source find . -name "*.csv" | xargs tar cvf - | (cd ../destination ; tar xfp -)
Sono pronto a contarlo come una riga, il cd source
è una shell incorporata.
Commenti
-
tar
ha lopzione-C
per evitare di dover prima cambiare la directory.
-m
è una scorciatoia per--prune-emty-dirs
.-R
può essere aggiunta per copiare la struttura della directory principale di source. (cfr. la mia risposta qui.)