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?
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.
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.
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.
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.
Le poisson Shell a un réponse bien plus jolie à ceci:
???? cp (correspondance de chaîne -v '* .excluded.names' - srcdir/*) destdir
Tapez _cp *
_, tapez CtrlX* et juste voir ce qui se passe. ce n'est pas dangereux Je promets
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.
cp -r `ls -A | grep -v "c"` $HOME/
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/
Développer sur commentaire de mvds , cela fonctionne pour moi
cd dotfiles
tar -c --exclude .git --exclude README . | tar -x -C ~/dotfiles2
C'est relatif au répertoire source.
Ceci exclura le répertoire source/.git
de la copie.
rsync -r --exclude '.git' source target
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
rsync
rsync -r --verbose --exclude 'exclude_pattern' ./* /to/where/
et essayez d'abord avec l'option -n pour voir ce qui va être copié
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.
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.
mv tobecopied/tobeexcluded .
cp -r tobecopied dest/
mv tobeexcluded tobecopied/
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 :
/
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.Le chemin --exclude
est relatif directement à la source. Même si vous mettez le chemin absolu complet, cela ne fonctionnera pas.
-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.
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
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/
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.
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).
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.