Linux: copia tutti i file corrispondenti al modello da dir e sottodir in una singola dir


31

Se volessi copiare tutti i *.sofile da srca dstfarei:

cp src/*.so dst

Tuttavia, voglio copiare tutti *.soi file da src e IT di sottodirectory in dst. Qualche indizio?

Risposte:


36

Provare:

find src/ -type f | grep -i so$ | xargs -i cp {} dst

17
findpuò fare pattern matching ed eseguire comandi. Non è necessario find src/ -type f -name '*.so' -exec cp '{}' dst/ ';'
convogliare il

1
Sì, può, tuttavia, spesso è più facile leggere una pipeline, anche le capacità di corrispondenza dei grepmodelli superano di gran lunga i semplici modelli di shell utilizzati nel -nameparametro find. xargsè anche molto più potente del -execparametro to find.
Mike Insch,

2
La soluzione di @jaquer è molto migliore perché su MacOSX l'utilità xargs non ha l'opzione -i. Ma la sua soluzione funziona come un fascino.
bialix,

Stavo lottando con un messaggio di errore sull'argomento -i di xargs fino a quando non ho letto il commento di @bialix sulla soluzione di Jaquer, che ha funzionato perfettamente sul mio Mac. Grazie
svannoy,

Questo creerà le sottodirectory secondo necessità?
Lennart Rolland,

15

Se stai usando Bash, puoi attivare l' globstar opzione shell per abbinare ricorsivamente file e directory:

shopt -s globstar
cp src/**/*.so dst

Se devi trovare file i cui nomi iniziano con ., e / o file dentro e sotto le directory i cui nomi iniziano con ., imposta anche l' dotglobopzione (es. Con shopt -s dotglob). Puoi impostarli entrambi in un solo comando:

shopt -s globstar dotglob

Non copia i file nelle sottodirectory che iniziano con a. nel loro nome
rboy

8

Ho provato il comando suggerito da Mike:

find src/ -type f | grep -i so$ | xargs -i cp {} dst

ma alla fine ha scaricato tutti i file nella directory dstcon i relativi percorsi persi.

Per mantenere i percorsi relativi, il comando deve essere modificato in questo modo:

find src/ -type f | grep -i so$ | xargs -i cp {} dst/{}

7
+1. Tuttavia, ciò presuppone che esistano le directory corrispondenti ai percorsi di origine relativi dst. Nel caso non fosse così, utilizzare cp --parents. Inoltre, assicurati di citare i nomi dei file. Pertanto: ... | xargs -i cp --parents "{}" dst(si noti che l'ultimo argomento a cpè ora "solo" la directory di destinazione). Il comando può essere reso ancora più breve (e probabilmente più veloce) con la -tbandiera: ... | xargs cp --parents -t dst.
Stephan202,

1
@ Stephan202 ho dovuto usare... | xargs cp {} --parents -t dst.
warvariuc l'

per quelli su un Mac, --parentsnon è disponibile. Ho usato dittoal suo posto: stackoverflow.com/questions/11246070/cp-parents-option-on-mac
Bryan Young

3

Un altro modo per farlo è così:

find src/ -type f -name "*.so" -exec cp {} dst/ \;

E questo dovrebbe ridurre il numero di cpprocessi: ... -exec cp -t dst/ {} +.
Kamil Maciorowski,

Ehi Kamil! Grazie per il commento! Potete per favore spiegarmi come la vostra soluzione rende le cose più veloci! Sempre disposto a saperne di più :)
Kyriakos

Quando si termina -execcon ;, {}è sostituito da un percorso alla volta. Ne ottieni uno separato cpper ogni file. Con la +sintassi findsostituisce {}con risultati multipli (fino a un limite definito dal sistema della lunghezza della riga di comando; restrizione: {}deve essere l'ultima cosa prima +, quindi cp -t). Creare e terminare un processo è una cosa relativamente costosa. Per questo motivo è consigliabile utilizzarlo +ogni volta che si prevedono molti risultati. In questo caso la copia di molti file potrebbe richiedere comunque molto tempo, quindi la differenza potrebbe passare inosservata; tuttavia è una buona pratica.
Kamil Maciorowski il

1

Il grep può essere sostituito usando find's -name :

find src/ -type f -name "*.so" | xargs -i cp {} dst/{}
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.