Comment utiliser la commande 'cp' pour exclure un répertoire spécifique?
411
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 d'option --exclude. Alors, comment puis-je y parvenir?
Notez que l' option dir thefoldertoexcludeaprès --excludeest relative à sourcefolder, c'est-à-dire sourcefolder/thefoldertoexclude.
Vous pouvez également ajouter -npour un essai à sec pour voir ce qui sera copié avant d'effectuer une opération réelle, et si tout va bien, supprimez -nde la ligne de commande.
D'accord, vous ne pouvez pas battre la simplicité et la puissance de--exclude
Matthew Wilcoxson
31
est le thefoldertoexcluderelatif au sourcefolderou le répertoire de travail actuel? merci
Beebee
46
C'est relatif au dossier source. Cela exclura la copie du dossier source / .git. rsync -r --exclude '.git' source target
orkoden
15
Peut-être que je me trompe, mais je pense que c'est une bonne pratique d'ajouter des "commutateurs" avant "paramètres". La page de manuel de rsync rapporte également --exclude utilisable comme avec la syntaxe "=" ou sans. Donc, pour standardiser les systèmes d'exploitation, j'utiliserais rsync -av --progress --exclude="thefoldertoexclude" sourcefolder /destinationfolder- de toute façon un vote positif pour le rsync au lieu de la recherche, car vous pouvez facilement utiliser des chemins absolus pour la source tandis que dans la recherche, c'est plus difficile car il utilise le {}dans le dst.
Xavi Montero, le
1
@mamun Bien sûr, par exemple, du serveur distant à la machine locale: $ rsync [email protected]:/var/www/mypage /var/www/mylocalpage/ou du local à distant$ rsync /var/www/mylocalpage/ [email protected]:/var/www/mypage
sobi3ch
84
Eh bien, si l'exclusion de certains modèles de nom de fichier devait être effectuée par chaque utilitaire de fichier unix-ish (comme cp, mv, rm, tar, rsync, scp, ...), une immense duplication des efforts se produirait. Au lieu de cela, ces choses peuvent être effectuées dans le cadre de la globalisation , c'est-à-dire par votre shell.
Donc, vous venez de mettre un motif à l'intérieur !(), et cela annule la correspondance. Le modèle peut être arbitrairement complexe, à partir de l'énumération des chemins individuels (comme Vanwaril le montre dans une autre réponse):, !(filename1|path2|etc3)à des choses semblables à des regex avec des étoiles et des classes de caractères. Reportez-vous à la page de manuel pour plus de détails.
Je pense que vous avez besoin de l' -pathargument pour tester les hiérarchies de chemins, pas
James Murty
3
Et vous aurez également besoin d'un point-virgule à la fin:find . -type f -not -path '*/not-from-here/*' -exec cp '{}' '/dest/{}' \;
Matthew Wilcoxson
1
Wow, ça ne me laissera pas: "Les modifications doivent être composées d'au moins 6 caractères"!
Matthew Wilcoxson
1
@MatthewWilcoxson Meh. Ces restrictions seront levées dès que vous gagnerez un peu plus de rep. J'ai modifié la réponse en conséquence. Merci encore!
Linus Kleen
1
@Henning pourquoi pas rsync? Parce qu'il peut ne pas être présent dans le système! tandis que find, cpest toujours à leur place. Ou vous, du genre de gars, qui avez installé 2 concerts pour faire des choses simples?
Création d'une fonction shell qui simplifie l'utilisation du chemin source personnalisé et l'exclusion d'un seul fichier ou répertoire: # $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
échoue avec les répertoires avec des espaces
Sérgio
27
Le moyen le plus simple que j'ai trouvé, où vous pouvez copier tous les fichiers à l'exception des fichiers et des dossiers simplement en ajoutant leurs noms entre parenthèses:
Vous pouvez sauter le supplément lset simplement le faire cp !(file1|file1) dest.
Shawn Chin
N'utilisez pas -laR. il ajoute une chaîne qui interfère avec cp. cp $(ls folder/!exclude_folder0|exclude_folder1)) dest
LAL
5
Une autre option plus simple consiste à installer et à utiliser rsync qui a une option --exclude-dir, et peut être utilisé pour les fichiers locaux et distants.
rsyncest en fait assez délicat. avoir à faire plusieurs tests pour le faire fonctionner.
Supposons que vous souhaitiez copier /var/www/htmldans, /var/www/devmais que vous deviez exclure le/var/www/html/site/video/ répertoire, peut-être en raison de sa taille. La commande serait:
La dernière barre oblique /dans la source est nécessaire, sinon elle copiera également le répertoire source plutôt que son contenu et deviendra /var/www/dev/html/xxxx, ce qui n'est peut-être pas ce que vous voulez.
Le --excludechemin est relatif à la source directement. Même si vous mettez le chemin absolu complet, cela ne fonctionnera pas.
-vest pour verbeux, -aest pour le mode archive, ce qui signifie que vous voulez la récursivité et que vous souhaitez conserver presque tout.
attention aux entrées de répertoire contenant des espaces.
Paulo Scardine
3
Il s'agit d'une modification de la réponse de Linus Kleen. Sa réponse n'a pas fonctionné pour moi car il y en aurait un. ajouté devant le chemin du fichier que cp n'aime pas (le chemin ressemblerait à source / .destination / file).
Pas assez peut-être - mais c'est la seule option que j'ai trouvée ici qui fonctionne avec cpun shell POSIX standard comme sh.
tomekwi
1
Cette réponse est considérablement sous-estimée. C'est la réponse la plus compatible, la plus facile à lire et à comprendre. Bravo, je ne sais pas pourquoi je n'y ai pas pensé.
Robert Talada
Merci @RobertTalada, jusqu'où ira la réponse à partir de maintenant? ️🌈
lama12345
0
J'utilise une boucle "do while" pour lire la sortie 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 de modèles que je veux que je ne veux pas. Vous pouvez inverser la logique avec un -not devant les drapeaux -iname:
J'utilise ce qui précède pour copier tous les fichiers de type de musique qui sont plus récents sur mon serveur que les fichiers sur un Western Digital TV Live Hub que j'ai monté dans / 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 copier, 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:
La première partie lstous les fichiers mais les fichiers spécifiques cachés avec indicateur -I. La sortie de lsest utilisée comme entrée standard pour la deuxième partie. xargsconstruire et exécuter la commande à cp -rf -t destdirpartir de l'entrée standard. l'indicateur -rsignifie copier les répertoires de manière récursive, -fsignifie copier les fichiers de force qui écraseront les fichiers dans le destdir, -tspécifiez la copie du répertoire de destination vers.
tar -c | tar -x
?Réponses:
rsync est rapide et facile:
Vous pouvez utiliser
--exclude
plusieurs fois.Notez que l' option dir
thefoldertoexclude
après--exclude
est relative àsourcefolder
, c'est-à-diresourcefolder/thefoldertoexclude
.Vous pouvez également ajouter
-n
pour un essai à sec pour voir ce qui sera copié avant d'effectuer une opération réelle, et si tout va bien, supprimez-n
de la ligne de commande.la source
--exclude
thefoldertoexclude
relatif ausourcefolder
ou le répertoire de travail actuel? mercirsync -av --progress --exclude="thefoldertoexclude" sourcefolder /destinationfolder
- de toute façon un vote positif pour le rsync au lieu de la recherche, car vous pouvez facilement utiliser des chemins absolus pour la source tandis que dans la recherche, c'est plus difficile car il utilise le{}
dans le dst.$ rsync [email protected]:/var/www/mypage /var/www/mylocalpage/
ou du local à distant$ rsync /var/www/mylocalpage/ [email protected]:/var/www/mypage
Eh bien, si l'exclusion de certains modèles de nom de fichier devait être effectuée par chaque utilitaire de fichier unix-ish (comme cp, mv, rm, tar, rsync, scp, ...), une immense duplication des efforts se produirait. Au lieu de cela, ces choses peuvent être effectuées dans le cadre de la globalisation , c'est-à-dire par votre shell.
frapper
man 1 bash
, / extglob .Exemple:
Donc, vous venez de mettre un motif à l'intérieur
!()
, et cela annule la correspondance. Le modèle peut être arbitrairement complexe, à partir de l'énumération des chemins individuels (comme Vanwaril le montre dans une autre réponse):,!(filename1|path2|etc3)
à des choses semblables à des regex avec des étoiles et des classes de caractères. Reportez-vous à la page de manuel pour plus de détails.zsh
man 1 zshexpn
, / génération de nom de fichier .Vous pouvez faire
setopt KSH_GLOB
et utiliser des modèles de type bash. Ou,Correspond donc au
x~y
modèlex
, mais exclut le modèley
. Encore une fois, pour plus de détails, reportez-vous à la page de manuel.poisson nouveau!
La coquille de poisson a une réponse beaucoup plus jolie à cela:
Bonus pro-tip
Tapez
cp *
, appuyez CtrlX*et voyez ce qui se passe. ce n'est pas nocif je le prometsla source
zsh
quand même.setopt -u extglob
.Pourquoi utiliser
rsync
quand vous pouvez le faire:Cela suppose que la structure du répertoire cible est la même que celle de la source.
la source
-path
argument pour tester les hiérarchies de chemins, pasfind . -type f -not -path '*/not-from-here/*' -exec cp '{}' '/dest/{}' \;
rsync
? Parce qu'il peut ne pas être présent dans le système! tandis quefind
,cp
est toujours à leur place. Ou vous, du genre de gars, qui avez installé 2 concerts pour faire des choses simples?la source
# $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 }
Le moyen le plus simple que j'ai trouvé, où vous pouvez copier tous les fichiers à l'exception des fichiers et des dossiers simplement en ajoutant leurs noms entre parenthèses:
la source
-bash: !: event not found
Développer le commentaire de mvds , cela fonctionne pour moi
la source
C'est relatif au répertoire source.
Cela exclura le répertoire
source/.git
d'être copié.la source
rsync
et essayez d'abord avec l'option -n pour voir ce qui va être copié
la source
Je suppose que vous utilisez bash ou dash. Est-ce que cela fonctionnerait?
Faire un ls en excluant les fichiers dont vous ne voulez pas, et l'utiliser comme premier argument pour cp
la source
ls
et simplement le fairecp !(file1|file1) dest
.cp $(ls folder/!exclude_folder0|exclude_folder1)) dest
Une autre option plus simple consiste à installer et à utiliser rsync qui a une option --exclude-dir, et peut être utilisé pour les fichiers locaux et distants.
la source
rsync
est en fait assez délicat. avoir à faire plusieurs tests pour le faire fonctionner.Supposons que vous souhaitiez copier
/var/www/html
dans,/var/www/dev
mais que vous deviez exclure le/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 copiera également le répertoire source plutôt que son contenu et deviendra/var/www/dev/html/xxxx
, ce qui n'est peut-être pas ce que vous voulez.Le
--exclude
chemin est relatif à la source directement. Même si vous mettez le chemin absolu complet, cela ne fonctionnera pas.-v
est pour verbeux,-a
est pour le mode archive, ce qui signifie que vous voulez la récursivité et que vous souhaitez conserver presque tout.la source
Edit: oublié d'exclure également le chemin cible (sinon il serait récursivement copié).
la source
Il s'agit d'une modification de la réponse de Linus Kleen. Sa réponse n'a pas fonctionné pour moi car il y en aurait un. ajouté devant le chemin du fichier que cp n'aime pas (le chemin ressemblerait à source / .destination / file).
Cette commande a fonctionné pour moi:
find . -type f -not -path '*/exlude-path/*' -exec cp --parents '{}' '/destination/' \;
la commande --parents conserve la structure du répertoire.
la source
la source
Déplacez-le simplement temporairement dans un répertoire caché (et renommez-le après, si vous le souhaitez).
la source
cp
un shell POSIX standard commesh
.J'utilise une boucle "do while" pour lire la sortie 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 de modèles que je veux que je ne veux pas. Vous pouvez inverser la logique avec un -not devant les drapeaux -iname:
J'utilise ce qui précède pour copier tous les fichiers de type de musique qui sont plus récents sur mon serveur que les fichiers sur un Western Digital TV Live Hub que j'ai monté dans / 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 copier, 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:
la source
La première partie
ls
tous les fichiers mais les fichiers spécifiques cachés avec indicateur-I
. La sortie dels
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 les fichiers de force qui écraseront les fichiers dans ledestdir
,-t
spécifiez la copie du répertoire de destination vers.la source
cp -r
ls -A | grep -v "Excluded_File_or_folder"
../$target_location -vla source