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?

David Liu
quelle
18
rsync?
Ajreal
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.

Strang
quelle
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 [email protected]:/var/www/mypage /var/www/mylocalpage/oder vom lokalen zum Remote- $ rsync /var/www/mylocalpage/ [email protected]:/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

ulidtko
quelle
@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.

Linus Kleen
quelle
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/
Essig Kumar
quelle
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/
sichere Kurve
quelle
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
13

Dies erweitert den Kommentar von mvds und funktioniert für mich

cd dotfiles
tar -c --exclude .git --exclude README . | tar -x -C ~/dotfiles2
Steven Penny
quelle
10

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

rsync -r --exclude '.git' source target
Niyaz Ahmed Qureshi
quelle
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

dzon
quelle
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

Vanwaril
quelle
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.

ehudokai
quelle
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.

LeOn - Han Li
quelle
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).

Sudo Arbeit
quelle
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.

Milan Simek
quelle
1
mv tobecopied/tobeexcluded .
cp -r tobecopied dest/
mv tobeexcluded tobecopied/
John Smith
quelle
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
lama12345
quelle
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/
user3610268
quelle
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.

LouisXW
quelle
0

cp -r ls -A | grep -v "Excluded_File_or_folder"../$target_location -v

Shashwot Risal
quelle