Copia il tipo di file specifico mantenendo la struttura delle cartelle


108

Ho una struttura di cartelle con un mucchio di file * .csv sparsi tra le cartelle. Ora voglio copiare tutti i file * .csv in un'altra destinazione mantenendo la struttura delle cartelle.

Funziona facendo:

cp --parents *.csv /target
cp --parents */*.csv" /target
cp --parents */*/*.csv /target
cp --parents */*/*/*.csv /target
...

e così via, ma vorrei farlo usando un solo comando.

Risposte:


126

C'è qualche motivo per cui le persone resistono all'uso di find -exec? È molto utile.

find . -name '*.csv' -exec cp --parents \{\} /target \;

Conosci i tuoi strumenti. ;-)


62
Probabilmente a causa di questo \ {\} \;
igo,

12
'{}'funziona altrettanto bene
OrangeDog,

3
Anche se -execdirè più sicuro di -exec, semplicemente sostituendo l'uno con l'altro non si conserva la struttura delle cartelle come previsto.
Simon Shine,

2
Perché ricevo il messaggio "Ometti directory" quando provo a copiarli con il tuo comando?
Vicky Dev,

4
Puoi spiegare perché qui è necessario sfuggire alle parentesi graffe?
Noumenon,

46

Puoi anche usarlo rsyncper questo.

$ rsync -a --prune-empty-dirs --include '*/' --include '*.csv' --exclude '*' source/ target/

Se si desidera mantenere directory vuote dall'albero dei sorgenti, saltare l' --prune-empty-dirsopzione:

$ rsync -a --include '*/' --include '*.csv' --exclude '*' source/ target/

Se non si desidera conservare collegamenti simbolici, date di modifica, autorizzazioni per file, proprietari, ecc., Sostituire -acon un'altra combinazione di -rlptgoD. ;-)


1
-mè una scorciatoia per --prune-emty-dirs.
Geremia,

Inoltre, è -Rpossibile aggiungere l' opzione per copiare la struttura della directory padre dell'origine. (cfr. la mia risposta qui.)
Geremia,

-R funziona per me! Grazie
gigi2

32

Puoi usare 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 li copierà in / target mantenendo la struttura di directory radicata ..

Se usi

find /path/to/files -name '*.csv' | cpio -pdm /target

troverà tutti i file dentro /path/to/filese sotto e li copierà in /target/path/to/filese sotto.


3
Ho provato tutte le risposte dall'alto verso il basso fino a questa, e questa è stata l'unica che ha funzionato al primo tentativo
OscarRyz,

21

Il cpcomando consente più argomenti di origine:

cp **/*.csv --parents ../target

CAVEAT: sto usando un glob ricorsivo qui; questa è l' globstaropzione in Bash 4+ e ksh, ed è supportata per impostazione predefinita in zsh. I globi ricorsivi non corrispondono a file e cartelle nascosti e alcune implementazioni seguono collegamenti simbolici mentre altre no .

Se la tua shell non supporta globi 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 sarà abbinare cartelle e file nascosti. findsupporta anche la specifica dell'opportunità di seguire i link simbolici, il che può essere utile.

questo è esattamente quello che ho provato (il glob ricorsivo) e ne ho trovati alcuni ma non tutti? abbastanza strano. Ho ottenuto lo stesso esatto risultato usando lo script npm copyfiles ma se uso il comando find trova tutto ...
Randyaa

@Randyaa Avrò bisogno di ulteriori dettagli su quali file, esattamente, non sono stati trovati per aiutarti. Puoi trovare la discussione qui e continuare qui sul comportamento preciso del glob ricorsivo utile.
Kyle Strand

1
risulta che glob ricorsivo non è stato abilitato per qualche motivo ... Non l'ho mai incontrato prima, ma l'ho corretto con solo un'esecuzione di shopt -s globstarimmediatamente prima del mio comando e tutto va bene. Grazie per il seguito!
Randyaa,

--parentsera quello che stavo cercando. grazie
Josh

17

Questo ha funzionato per me:

find -name "*.csv" | xargs cp --parents -t /target


La migliore risposta con la sintassi più semplice. Funziona bene ed è facile da ricordare. In molti casi find [things] | xargs [do stuff]è molto potente.
Everyday Astronaut

Concordato. Molto semplice rispetto ad alcune delle altre risposte.
Tim B

1
Si rompe se hai spazi nei nomi dei file
Michele Piccolini,

@MichelePiccolini Gli spazi nei nomi dei file possono essere gestiti con find -print0e xargs -0.
pasztorpisti,

8

Supponendo di voler replicare questa struttura da ./sourcea ./destination:

cd source
find . -name "*.csv" | xargs tar cvf - | (cd ../destination ; tar xfp -)

Sono pronto a considerarlo come una riga, l' cd sourceessere una shell incorporata.


2
Non penso che significhi davvero un comando - semplicemente non doversi preoccupare come il suo esempio;)

tarha l' -Copzione per evitare di dover prima cambiare la directory.
Bart il

8

Dalla rsyncmanpage:

-R, --relativo

Usa percorsi relativi. Ciò significa che i nomi di percorso completi specificati nella riga di comando vengono inviati al server anziché solo le ultime parti dei nomi dei file. Ciò è particolarmente utile quando si desidera inviare più directory diverse contemporaneamente. Ad esempio, se hai utilizzato questo comando:

rsync -av /foo/bar/baz.c remote:/tmp/

... questo creerebbe un file chiamato baz.c in / tmp / sul computer remoto. Se invece hai usato

rsync -avR /foo/bar/baz.c remote:/tmp/

quindi un file chiamato /tmp/foo/bar/baz.c verrebbe creato sul computer remoto, mantenendo il suo percorso completo. Questi elementi del percorso extra sono chiamati "directory implicite" (ovvero le directory "pippo" e "pippo / bar" nell'esempio sopra).

Quindi, anche questo funzionerebbe:

rsync -armR --include="*/" --include="*.csv" --exclude="*" /full/path/to/source/file(s) destination/
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.