web-dev-qa-db-fra.com

Comment utiliser la commande 'cp' pour exclure un répertoire spécifique?

Je souhaite copier tous les fichiers d'un répertoire, à l'exception de certains fichiers d'un sous-répertoire spécifique. J'ai remarqué que la commande 'cp' n'avait pas l'option --exclude. Alors, comment puis-je y parvenir?

361
David Liu

rsync est rapide et facile:

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

Vous pouvez utiliser --exclude plusieurs fois.

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

Notez que l'option dir thefoldertoexclude après --exclude est relative à la sourcefolder, c'est-à-dire sourcefolder/thefoldertoexclude.

Vous pouvez également ajouter -n pour une exécution à sec pour voir ce qui sera copié avant d'effectuer une opération réelle. Si tout va bien, supprimez -n de la ligne de commande.

609
hank

Eh bien, si chaque utilitaire de fichier unix-ish (comme cp, mv, rm, tar, rsync, scp, ...) devait exclure certains modèles de nom de fichier, une duplication considérable des efforts serait nécessaire. Au lieu de cela, de telles choses peuvent être faites dans le cadre de globbing , c'est-à-dire par votre Shell.

bash

Lien au manuel, recherchez extglob.

Exemple:

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

Donc, vous venez de mettre un motif dans !(), et cela annule la correspondance. Le motif peut être arbitrairement complexe, à partir de l'énumération de chemins individuels (comme le montre Vanwaril dans une autre réponse): !(filename1|path2|etc3), de choses semblables à des expressions rationnelles avec des étoiles et des classes de caractères. Reportez-vous à la page de manuel pour plus de détails.

zsh

Lien au manuel, section "génération de nom de fichier".

Vous pouvez faire _setopt KSH_GLOB_ et utiliser des modèles similaires à bash. Ou,

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

Donc, x~y correspond au modèle x, mais exclut le modèle y. Encore une fois, pour plus de détails, reportez-vous à la page de manuel.


poissonnouveau!

Le poisson Shell a un réponse bien plus jolie à ceci:

 ???? cp (correspondance de chaîne -v '* .excluded.names' - srcdir/*) destdir 

Bonus pro-tip

Tapez _cp *_, tapez CtrlX* et juste voir ce qui se passe. ce n'est pas dangereux Je promets

77
ulidtko

Pourquoi utiliser rsync quand vous pouvez faire:

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

Cela suppose que la structure du répertoire cible soit la même que celle de la source.

43
Linus Kleen
cp -r `ls -A | grep -v "c"` $HOME/
33
vineet kumar

Le moyen le plus simple que j'ai trouvé, où vous pouvez copier tous les fichiers, à l'exception des fichiers et des dossiers, en ajoutant simplement leurs noms entre parenthèses:

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

Développer sur commentaire de mvds , cela fonctionne pour moi

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

C'est relatif au répertoire source.
Ceci exclura le répertoire source/.git de la copie.

rsync -r --exclude '.git' source target
8
Niyaz Ahmed Qureshi

Je suppose que vous utilisez bash ou dash. Cela fonctionnerait-il?

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

Faire un ls en excluant les fichiers que vous ne voulez pas, et en l’utilisant comme premier argument de cp

7
Vanwaril

rsync

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

et essayez d'abord avec l'option -n pour voir ce qui va être copié

7
dzon

Une autre option plus simple consiste à installer et à utiliser rsync, qui possède une option --exclude-dir et peut être utilisé à la fois pour les fichiers locaux et distants.

6
ehudokai

Ceci est une modification de la réponse de Linus Kleen. Sa réponse n'a pas fonctionné pour moi car il y aurait un. ajouté devant le chemin du fichier que cp n'aime pas (le chemin ressemblerait à source/.destination/fichier).

Cette commande a fonctionné pour moi:

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

la commande --parents préserve la structure de répertoires.

3
Milan Simek
mv tobecopied/tobeexcluded .
cp -r tobecopied dest/
mv tobeexcluded tobecopied/
2
John Smith

rsync est en fait assez délicat. faire plusieurs tests pour le faire fonctionner.

Supposons que vous vouliez copier /var/www/html dans /var/www/dev mais que vous ayez besoin de exclure/var/www/html/site/video/ répertoire peut-être en raison de sa taille. La commande serait:

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

Quelques mises en garde :

  1. La dernière barre oblique / dans la source est nécessaire, sinon elle copie également le répertoire source plutôt que son contenu et devient /var/www/dev/html/xxxx, ce qui n’est peut-être pas ce que vous voulez.
  2. Le chemin --exclude est relatif directement à la source. Même si vous mettez le chemin absolu complet, cela ne fonctionnera pas.

  3. -v est destiné au verbose, -a est destiné au mode d'archivage, ce qui signifie que vous voulez une récursion et que vous souhaitez presque tout conserver.

2
LeOn - Han Li

Il suffit de le déplacer temporairement dans un répertoire caché (et de le renommer après, si vous le souhaitez).

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

J'utilise une boucle "do while" pour lire le résultat de la commande find. Dans cet exemple, je fais correspondre (plutôt que d'exclure) certains modèles, car il y a un nombre plus limité de correspondances que je ne veux pas. Vous pouvez inverser la logique avec un -not devant les drapeaux -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

J'utilise ce qui précède pour copier tous les fichiers de type de musique plus récents sur mon serveur que ceux d'un disque Western Digital Live Hub que j'ai montés sur/media/wd. J'utilise ce qui précède parce que j'ai beaucoup de fichiers DVD, mpeg, etc. que je veux exclure ET parce que, pour une raison quelconque, rsync semble être en cours de copie, mais après avoir regardé le périphérique wd, les fichiers ne sont pas là malgré aucun erreurs lors de la rsync avec cette commande:

    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/
1
user3610268

Une solution consisterait à utiliser find -0 avec -Prune pour rechercher tous les fichiers et répertoires à déplacer, puis à utiliser xargs -0 pour les copier.

1
Jason Orendorff
cp -rv `ls -A | grep -vE "dirToExclude|targetDir"` targetDir

Edit: a oublié d'exclure également le chemin cible (sinon, il le copierait de manière récursive).

1
sudo work
ls -I "filename1" -I "filename2" | xargs cp -rf -t destdir 

La première partie ls tous les fichiers mais des fichiers spécifiques masqués avec l'indicateur -I. La sortie de ls est utilisée comme entrée standard pour la deuxième partie. xargs construire et exécuter la commande cp -rf -t destdir à partir de l'entrée standard. l'indicateur -r signifie copier les répertoires de manière récursive, -f signifie copier des fichiers avec force, ce qui écrasera les fichiers de la destdir, -t spécifier le répertoire de destination dans lequel copier.

0
LouisXW