Wie verwende ich den Befehl 'cp', um ein bestimmtes Verzeichnis auszuschließen?


409

Ich möchte alle Dateien in einem Verzeichnis kopieren, mit Ausnahme einiger Dateien in einem bestimmten Unterverzeichnis. Ich habe festgestellt, dass der Befehl 'cp' keine Option --exclude hatte. Wie kann ich das erreichen?



6
tar -c | tar -x?
MVDS

1
@mvds, stimme dir zu, die Verwendung von tar mit '--exclude' ist eine gute Idee.
Huang F. Lei

2
Mögliches Duplikat des
Kopierordners

Antworten:


702

rsync ist schnell und einfach:

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

Sie können --excludemehrere Male verwenden.

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

Beachten Sie, dass die Option dir thefoldertoexcludeafter --excluderelativ zu sourcefolder, dh , sourcefolder/thefoldertoexclude.

Sie können auch einen -nTrockenlauf hinzufügen, um zu sehen, was kopiert wird, bevor der eigentliche Vorgang ausgeführt wird. Wenn alles in Ordnung ist, entfernen Sie ihn -naus der Befehlszeile.


3
Einverstanden, Sie können die Einfachheit und Kraft von--exclude
Matthew Wilcoxson

31
ist das thefoldertoexcluderelativ zum sourcefolderoder dem aktuellen Arbeitsverzeichnis? danke
Beebee

45
Es ist relativ zum Quellordner. Dadurch wird die Ordnerquelle / .git vom Kopieren ausgeschlossen. rsync -r --exclude '.git' Quellziel
orkoden

15
Vielleicht irre ich mich, aber ich denke, es ist eine gute Praxis, "Schalter" vor "Parameter" hinzuzufügen. Auch die Manpage von rsync-Berichten - Ausschluss verwendbar wie mit der Syntax "=" oder ohne. Um sich betriebssystemübergreifend zu standardisieren, würde ich rsync -av --progress --exclude="thefoldertoexclude" sourcefolder /destinationfolder- ohnehin upvote für den rsync anstelle des find - verwenden, da Sie leicht absolute Pfade für die Quelle verwenden können, während es im find schwieriger ist, als {}im dst.
Xavi Montero

1
@mamun Natürlich zB vom Remote-Server zum lokalen Computer: $ rsync user@example.com:/var/www/mypage /var/www/mylocalpage/oder vom lokalen zum Remote- $ rsync /var/www/mylocalpage/ user@example.com:/var/www/mypage
Computer

84

Nun, wenn das Ausschließen bestimmter Dateinamenmuster von jedem Unix-ish-Dateidienstprogramm (wie cp, mv, rm, tar, rsync, scp, ...) durchgeführt werden müsste, würde eine immense Doppelarbeit auftreten. Stattdessen können solche Dinge als Teil des Globbings ausgeführt werden , dh durch Ihre Shell.

Bash

man 1 bash, / extglob .

Beispiel:

$ 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

Sie fügen also einfach ein Muster ein !()und es negiert die Übereinstimmung. Das Muster kann beliebig komplex sein, angefangen bei der Aufzählung einzelner Pfade (wie Vanwaril in einer anderen Antwort zeigt) !(filename1|path2|etc3)bis hin zu regexartigen Dingen mit Sternen und Zeichenklassen. Weitere Informationen finden Sie in der Manpage.

zsh

man 1 zshexpn, / Dateinamengenerierung .

Sie können setopt KSH_GLOBbashartige Muster erstellen und verwenden. Oder,

% 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

Entspricht also dem x~yMuster x, schließt jedoch das Muster aus y. Weitere Informationen finden Sie auf der Manpage.


Fisch neu!

Die Fischschale hat eine viel schönere Antwort darauf:

🐟 cp (Zeichenfolgenübereinstimmung -v '* .excluded.names' - srcdir / *) destdir

Bonus Pro-Tipp

Tippen Sie cp *, drücken Sie CtrlX*und sehen Sie, was passiert. Es ist nicht schädlich, das verspreche ich


@MikhailGolubtsov Vielleicht liegt das daran, dass Globbing nicht rekursiv ist und eine Ebene nach der anderen funktioniert. Herausgeschnitten. PS: Es funktioniert aber in zsh.
Ulidtko

3
Netter Pro-Tipp! Auf diese Weise können Sie einzelne Elemente einfach entfernen. Vielen Dank!
Taft

Übrigens, um erweiterte Mustervergleichsfunktionen in Bash zu deaktivieren, führen Sie aus setopt -u extglob.
Rockallite

49

Warum verwenden, rsyncwenn Sie Folgendes tun können:

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

Dies setzt voraus, dass die Zielverzeichnisstruktur mit der der Quelle übereinstimmt.


8
Ich denke, Sie brauchen das -pathArgument, um Pfadhierarchien zu testen, nicht -iname
James Murty

3
Und Sie brauchen auch ein Semikolon am Ende:find . -type f -not -path '*/not-from-here/*' -exec cp '{}' '/dest/{}' \;
Matthew Wilcoxson

1
Wow, es lässt mich nicht: "Bearbeitungen müssen mindestens 6 Zeichen sein"!
Matthew Wilcoxson

1
@ MatthewWilcoxson Meh. Diese Einschränkungen werden aufgehoben, sobald Sie etwas mehr Wiederholungen erhalten. Ich habe die Antwort entsprechend bearbeitet. Danke noch einmal!
Linus Kleen

1
@ Henning warum nicht rsync? Weil es möglicherweise nicht im System vorhanden ist! während find, cpist immer auf ihren Plätzen. Oder Sie von Leuten, die 2 Gig-Sachen installiert haben, um einfache Dinge zu tun?
Reishin

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

1
Arbeitete für mich in Windows 10 .sh
atwellpub

Eine Shell-Funktion wurde erstellt, die die Verwendung für den benutzerdefinierten # $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 }
Quellpfad

schlägt mit Verzeichnissen mit Leerzeichen fehl
Sérgio

27

Der einfachste Weg, den ich gefunden habe, bei dem Sie alle Dateien außer Dateien und Ordnern kopieren können, indem Sie ihre Namen in Klammern einfügen:

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

9
Funktioniert bei mir nicht Ich bekomme-bash: !: event not found
geneorama

8
shopt -s extglob (führen Sie dies aus, um! in cp, rm und anderen zu aktivieren)
imkost


10

Es ist relativ zum Quellverzeichnis.
Dadurch wird das Verzeichnis source/.gitvom Kopieren ausgeschlossen.

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

Was ist der Unterschied / die Verbesserung gegenüber der Top-Antwort?
Reduzierung der Aktivität

8

rsync

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

und versuchen Sie es zuerst mit der Option -n, um zu sehen, was kopiert werden soll


Was ist der Unterschied / die Verbesserung gegenüber der Top-Antwort?
Reduzierung der Aktivität

7

Ich nehme an, Sie verwenden Bash oder Dash. Würde das funktionieren?

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

Führen Sie ein ls aus, ohne die Dateien auszuschließen, die Sie nicht möchten, und verwenden Sie dies als erstes Argument für cp


9
Sie können das Extra überspringen lsund einfach tun cp !(file1|file1) dest.
Shawn Chin

Verwenden Sie nicht -laR. Es wird eine Zeichenfolge hinzugefügt, die cp stört. cp $(ls folder/!exclude_folder0|exclude_folder1)) dest
LAL

5

Eine weitere einfachere Option ist die Installation und Verwendung von rsync mit der Option --exclude-dir, das sowohl für lokale als auch für entfernte Dateien verwendet werden kann.


4

rsyncist eigentlich ziemlich knifflig. müssen mehrere Tests durchführen, damit es funktioniert.

Angenommen, Sie kopieren möchten /var/www/htmlzu /var/www/devmüssen aber ausschließen /var/www/html/site/video/ vielleicht Verzeichnis aufgrund seiner Größe. Der Befehl wäre:

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

Einige Einschränkungen :

  1. Der letzte Schrägstrich /in der Quelle wird benötigt, andernfalls wird auch das Quellverzeichnis anstelle seines Inhalts kopiert und wird/var/www/dev/html/xxxx , was möglicherweise nicht das ist, was Sie wollen.
  2. Der --excludePfad ist direkt relativ zur Quelle. Selbst wenn Sie den vollständigen absoluten Pfad angeben, funktioniert dies nicht.

  3. -vist für ausführlich, -aist für den Archivierungsmodus, was bedeutet, dass Sie eine Rekursion wünschen und fast alles beibehalten möchten.


eine einfache Lösung, die sich um Sonderzeichen und Leerzeichen kümmert
Sérgio

Vielen Dank für die Erklärung der Parameter, im Gegensatz zur aktuellen Top-Antwort!
Reduzierung der Aktivität

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

Bearbeiten: Ich habe vergessen, auch den Zielpfad auszuschließen (andernfalls würde er rekursiv kopiert).


4
Achten Sie auf Verzeichniseinträge mit Leerzeichen.
Paulo Scardine

3

Dies ist eine Modifikation von Linus Kleens Antwort. Seine Antwort hat bei mir nicht funktioniert, weil es eine geben würde. vor dem Dateipfad hinzugefügt, den cp nicht mag (der Pfad würde wie source / .destination / file aussehen).

Dieser Befehl hat bei mir funktioniert:

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

Der Befehl --parents behält die Verzeichnisstruktur bei.


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

1

Verschieben Sie es einfach vorübergehend in ein verstecktes Verzeichnis (und benennen Sie es anschließend um, falls gewünscht).

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

1
Vielleicht nicht schön - aber dies ist die einzige Option, die ich hier gefunden habe und die mit cpeiner Standard-POSIX-Shell funktioniert sh.
Tomekwi

0

Ich benutze eine "do while" -Schleife, um die Ausgabe des Befehls find zu lesen. In diesem Beispiel stimme ich mit bestimmten Mustern überein (anstatt sie auszuschließen), da es eine begrenzte Anzahl von Musterübereinstimmungen gibt, die ich möchte, als die ich nicht möchte. Sie können die Logik mit einem -not vor den -iname-Flags umkehren:

    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

Ich verwende das oben Gesagte, um alle Musiktypdateien zu kopieren, die auf meinem Server neuer sind als die Dateien auf einem Western Digital TV Live Hub, den ich unter / media / wd gemountet habe. Ich benutze das oben genannte, weil ich viele DVD-Dateien, MPEGs usw. habe, die ich ausschließen möchte UND weil rsync aus irgendeinem Grund so aussieht, als würde es kopiert, aber nachdem ich mir das wd-Gerät angesehen habe, sind die Dateien trotz nein nicht da Fehler während der Rsync mit diesem Befehl:

    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 

Der erste Teil lsalle Dateien aber versteckte bestimmte Dateien mit Flag -I. Die Ausgabe von lswird als Standardeingabe für den zweiten Teil verwendet. xargsBefehl cp -rf -t destdiraus Standardeingabe erstellen und ausführen . die Flag - -rMittel kopieren Verzeichnisse rekursiv, -fmittels Kopieren von Dateien mit Gewalt , welche die Dateien in die überschrieben werden destdir, -tum das Zielverzeichnis kopieren angeben.


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.