Come usare il comando 'cp' per escludere una directory specifica?


411

Voglio copiare tutti i file in una directory tranne alcuni file in una sottodirectory specifica. Ho notato che il comando 'cp' non aveva un'opzione --exclude. Quindi, come posso raggiungere questo obiettivo?



6
tar -c | tar -x?
mvds

1
@mvds, d'accordo con te, usare tar con '--exclude' è una buona idea.
Huang F. Lei

Risposte:


704

rsync è semplice e veloce:

rsync -av --progress sourcefolder /destinationfolder --exclude thefoldertoexclude

Puoi usare --excludemultipli volte.

rsync -av --progress sourcefolder /destinationfolder --exclude thefoldertoexclude --exclude anotherfoldertoexclude

Si noti che la directory thefoldertoexcludedopo --excludeopzione è relativo al sourcefolder, cioè sourcefolder/thefoldertoexclude.

Inoltre puoi aggiungere -nper la corsa a secco per vedere cosa verrà copiato prima di eseguire un'operazione reale e, se tutto è a posto, rimuovilo -ndalla riga di comando.


3
D'accordo, non puoi battere la semplicità e la potenza di--exclude
Matthew Wilcoxson,

31
è il thefoldertoexcluderelativo al sourcefolderdir corrente di lavoro o? grazie
Beebee,

46
È relativo alla cartella di origine. Ciò escluderà la cartella source / .git dalla copia. rsync -r --exclude destinazione sorgente '.git'
orkoden

15
Forse mi sbaglio, ma penso che sia una buona pratica aggiungere "switch" prima di "parametri". Anche la pagina man dei rapporti rsync --esclude utilizzabile come con la sintassi "=" o senza. Quindi, per standardizzare su tutti i sistemi operativi, rsync -av --progress --exclude="thefoldertoexclude" sourcefolder /destinationfolderuserei - comunque upvote per rsync invece che find, in quanto puoi facilmente usare percorsi assoluti per il sorgente mentre nella ricerca è più complicato come usa {}nel dst.
Xavi Montero,

1
@mamun Naturalmente ad es. dal server remoto al computer locale: $ rsync user@example.com:/var/www/mypage /var/www/mylocalpage/o dal locale al remoto$ rsync /var/www/mylocalpage/ user@example.com:/var/www/mypage
sobi3ch

84

Bene, se l'esclusione di determinati schemi di nomi di file dovesse essere eseguita da ogni utilità di file unix-ish (come cp, mv, rm, tar, rsync, scp, ...), si verificherebbe un'immensa duplicazione degli sforzi. Invece, tali cose possono essere fatte come parte del globbing , cioè dal tuo guscio.

bash

man 1 bash, / extglob .

Esempio:

$ shopt -s extglob
$ echo images / *
images / 004.bmp images / 033.jpg images / 1276338351183.jpg images / 2252.png
$ echo images /! (*. jpg)
images / 004.bmp images / 2252.png

Quindi hai appena inserito uno schema !()e questo annulla la partita. Lo schema può essere arbitrariamente complesso, a partire dall'enumerazione di percorsi individuali (come Vanwaril mostra in un'altra risposta): !(filename1|path2|etc3)a cose simili a regex con stelle e classi di personaggi. Fare riferimento alla pagina man per i dettagli.

zsh

man 1 zshexpn, / generazione del nome file .

Puoi fare setopt KSH_GLOBe usare schemi tipo bash. O,

% setopt EXTENDED_GLOB
% echo images / *
images / 004.bmp images / 033.jpg images / 1276338351183.jpg images / 2252.png
% echo images / * ~ * .jpg
images / 004.bmp images / 2252.png

Quindi x~ycorrisponde al modello x, ma esclude il modello y. Ancora una volta, per i dettagli completi consultare la manpage.


pesce nuovo!

Il pesce shell ha una risposta più bella molto a questo:

🐟 cp (string match -v '* .excluded.names' - srcdir / *) destdir

Bonus pro-tip

Digita cp *, premi CtrlX*e guarda cosa succede. non è dannoso lo prometto


@MikhailGolubtsov forse è perché il globbing non è ricorsivo e funziona a un livello alla volta. Redatto. PS: funziona zshperò.
Ulidtko,

3
Bel pro-tip! In questo modo è possibile rimuovere facilmente singoli elementi. Molte grazie!
taffit

A proposito, per disattivare le funzionalità estese di corrispondenza dei motivi in ​​Bash, eseguire setopt -u extglob.
Rockallite,

49

Perché usare rsyncquando puoi fare:

find . -type f -not -iname '*/not-from-here/*' -exec cp '{}' '/dest/{}' ';'

Ciò presuppone che la struttura della directory di destinazione sia la stessa di quella di origine.


8
Penso che tu abbia bisogno -pathdell'argomento per testare le gerarchie dei percorsi, non -iname
James Murty,

3
E alla fine avrai anche bisogno di un punto e virgola:find . -type f -not -path '*/not-from-here/*' -exec cp '{}' '/dest/{}' \;
Matthew Wilcoxson,

1
Caspita, non mi permette: "Le modifiche devono contenere almeno 6 caratteri"!
Matthew Wilcoxson,

1
@MatthewWilcoxson Meh. Tali restrizioni saranno revocate non appena avrai un po 'più di reputazione. Ho modificato la risposta di conseguenza. Grazie ancora!
Linus Kleen,

1
@Henning perché no rsync? Perché potrebbe non essere presente nel sistema! mentre find, cpè sempre al loro posto. O da tipi di ragazzi, che hai installato 2 GB di cose per fare cose semplici?
Reishin,

37
cp -r `ls -A | grep -v "c"` $HOME/

1
Ha funzionato per me in Windows 10 .sh
atwellpub il

Realizzata una funzione shell che semplifica l'utilizzo del percorso sorgente personalizzato e l'esclusione di un solo file o directory: # $1 = source path # $2 = destination path # $3 = filter copy_from_source_to_destination_except_filter() { cp -r $(ls -A $1 | grep -v -w $3 | awk -v path=$1 '{printf "%s/%s ", path, $1}') $2 }
ElectRocnic

fallisce con le directory con spazi
Sérgio

27

Il modo più semplice che ho trovato, in cui è possibile copiare tutti i file escludendo file e cartelle semplicemente aggiungendo i loro nomi tra parentesi:

shopt -s extglob
cp -r !(Filename1 | FoldernameX | Filename2) Dest/

9
Non funziona per me. Ricevo-bash: !: event not found
geneorama il

8
shopt -s extglob (esegui questo per abilitare! in cp, rm e altri)
imkost,


10

È relativo alla directory di origine.
Ciò escluderà la directory source/.gitdalla copia.

rsync -r --exclude '.git' source target

Qual è la differenza / miglioramento rispetto alla risposta migliore?
riduzione dell'attività

8

rsync

rsync -r --verbose --exclude 'exclude_pattern' ./* /to/where/

e prima provalo con l'opzione -n ​​per vedere cosa verrà copiato


Qual è la differenza / miglioramento rispetto alla risposta migliore?
riduzione dell'attività

7

Presumo che tu stia usando bash o dash. Funzionerebbe?

shopt -s extglob  # sets extended pattern matching options in the bash shell
cp $(ls -laR !(subdir/file1|file2|subdir2/file3)) destination

Eseguendo una ls escludendo i file non desiderati e utilizzandola come primo argomento per cp


9
Puoi saltare l'extra lse semplicemente farlo cp !(file1|file1) dest.
Shawn Chin,

Non usare -laR. aggiunge una stringa che interferisce con cp. cp $(ls folder/!exclude_folder0|exclude_folder1)) dest
LAL

5

Un'altra opzione più semplice è installare e usare rsync che ha un'opzione --exclude-dir e può essere usata sia per i file locali che per quelli remoti.


4

rsyncè in realtà abbastanza complicato. devi fare più test per farlo funzionare.

Diciamo che si desidera copiare /var/www/htmla /var/www/devma necessità di escludere le /var/www/html/site/video/ directory forse per le sue dimensioni. Il comando sarebbe:

rsync -av --exclude 'sites/video' /var/www/html/ /var/www/dev

Alcuni avvertimenti :

  1. È necessaria l'ultima barra /nella fonte, altrimenti copierà anche la directory di origine anziché il suo contenuto e diventerà /var/www/dev/html/xxxx, che forse non è quello che vuoi.
  2. Il --excludepercorso è direttamente relativo alla fonte. Anche se inserisci il percorso assoluto completo, non funzionerà.

  3. -vè per prolisso, -aè per la modalità archivio, il che significa che vuoi ricorsione e vuoi preservare quasi tutto.


una soluzione semplice che si prende cura di personaggi speciali e spazi bianchi
Sérgio,

Grazie per aver spiegato i parametri, a differenza dell'attuale risposta migliore!
riduzione dell'attività

3
cp -rv `ls -A | grep -vE "dirToExclude|targetDir"` targetDir

Modifica: dimenticato di escludere anche il percorso target (altrimenti verrebbe copiato in modo ricorsivo).


4
fare attenzione alle voci della directory contenenti spazi.
Paulo Scardine,

3

Questa è una modifica della risposta di Linus Kleen. La sua risposta non ha funzionato per me perché ci sarebbe un. aggiunto davanti al percorso del file che cp non piace (il percorso sembrerebbe source / .destination / file).

Questo comando ha funzionato per me:

find . -type f -not -path '*/exlude-path/*' -exec cp --parents '{}' '/destination/' \;

il comando --parents conserva la struttura della directory.


2
mv tobecopied/tobeexcluded .
cp -r tobecopied dest/
mv tobeexcluded tobecopied/

2

Basta spostarlo temporaneamente in una directory nascosta (e rinominarlo dopo, se lo si desidera).

mkdir .hiddendir
cp * .hiddendir -R
mv .hiddendir realdirname

1
Forse non abbastanza, ma questa è l'unica opzione che ho trovato qui che funziona con cpuna shell POSIX standard come sh.
tomekwi,

1
Questa risposta è drammaticamente sottovalutata. Questa è la risposta più compatibile, più facile da leggere e di facile comprensione. Complimenti, non so perché non ci abbia pensato.
Robert Talada,

Grazie @RobertTalada, fino a che punto andrà la risposta da adesso? ️‍🌈
lama12345,

0

Uso un ciclo "do while" per leggere l'output del comando find. In questo esempio, sto abbinando (piuttosto che escludendo) determinati modelli poiché esiste un numero più limitato di corrispondenze di motivi che desidero di quello che non desidero. È possibile invertire la logica con un -not davanti ai flag -iname:

    find . -type f -iname "*.flac" -o -print0 -iname "*.mp3" -print0 -o -iname "*.wav" -print0 -o -iname "*.aac" -print0 -o -iname "*.wma" -print0 | while read -d $'\0' file; do cp -ruv "$file" "/media/wd/network_sync/music/$file"; done

Uso quanto sopra per copiare tutti i file di tipo musicale più recenti sul mio server rispetto ai file su un Live Hub TV digitale occidentale che ho montato su / media / wd. Uso quanto sopra perché ho molti file DVD, mpeg, ecc. Che voglio escludere E perché per qualche ragione rsync sembra che stia copiando, ma dopo aver guardato il dispositivo wd, i file non sono lì nonostante errori durante il rsync con questo comando:

    rsync -av --progress --exclude=*.VOB --exclude=*.avi --exclude=*.mkv --exclude=*.ts --exclude=*.mpg --exclude=*.iso --exclude=*ar --exclude=*.vob --exclude=*.BUP --exclude=*.cdi --exclude=*.ISO --exclude=*.shn --exclude=*.MPG --exclude=*.AVI --exclude=*.DAT --exclude=*.img --exclude=*.nrg --exclude=*.cdr --exclude=*.bin --exclude=*.MOV --exclude=*.goutputs* --exclude=*.flv --exclude=*.mov --exclude=*.m2ts --exclude=*.cdg --exclude=*.IFO --exclude=*.asf --exclude=*.ite /media/2TB\ Data/data/music/* /media/wd/network_sync/music/

0
ls -I "filename1" -I "filename2" | xargs cp -rf -t destdir 

La prima parte di lstutti i file, ma nascosti file specifici con flag -I. L'output di lsviene utilizzato come input standard per la seconda parte. xargscompila ed esegui il comando cp -rf -t destdirdall'input standard. il flag -rsignifica -fricorrere in modo ricorsivo alle directory, significa forzare la copia dei file che sovrascriveranno i file in destdir, -tspecificare la copia della directory di destinazione in.


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.