205 votes

Copier un dossier de manière récursive, en excluant certains dossiers

J'essaie d'écrire un simple bash script qui copiera le contenu entier d'un dossier, y compris les fichiers et dossiers cachés, dans un autre dossier, mais je veux exclure certains dossiers spécifiques. Comment pourrais-je y parvenir ?

1 votes

J'imagine quelque chose comme find . -name * suivi de grep /v "exclude-pattern" pour filtrer ceux que vous ne voulez pas et ensuite suivi de cp pour faire la copie.

1 votes

J'ai essayé de faire quelque chose comme ça, mais je n'ai pas trouvé comment utiliser cp avec un tube.

1 votes

Cela devrait probablement aller au super utilisateur. La commande que vous cherchez est xargs. Vous pourriez aussi faire quelque chose comme deux tar reliés par un tuyau.

353voto

Kaleb Pederson Points 22428

Utilisez rsync :

rsync -av --exclude='path1/to/exclude' --exclude='path2/to/exclude' source destination

Notez que l'utilisation de source et source/ sont différents. Une barre oblique à la fin signifie qu'il faut copier le contenu du dossier source en destination . Sans la barre oblique de fin, cela signifie copier le dossier source en destination .

Alternativement, si vous avez beaucoup de répertoires (ou de fichiers) à exclure, vous pouvez utiliser la méthode suivante --exclude-from=FILEFILE est le nom d'un fichier contenant les fichiers ou les répertoires à exclure.

--exclude peut également contenir des caractères génériques, tels que --exclude=*/.svn*

0 votes

Si vous - comme moi - voulez copier récursivement une structure entière et ne garder qu'un certain type de fichiers, vous pouvez aussi utiliser rsync : rsync -rav --include=*/ --include=" .txt" --exclude= test/ mytest Ceci prendra tous les fichiers .txt du répertoire source et les copiera dans le répertoire de destination avec la structure intacte.

13 votes

Je suggère d'ajouter l'option --dry-run afin de vérifier quels fichiers vont être copiés.

0 votes

Je suis désolé mais rsync n'est pas installé par défaut sur tous les systèmes que je connais, tar par contre l'est.

42voto

Kyle Butt Points 3593

Utilisez du goudron avec un tuyau.

cd /source_directory
tar cf - --exclude=dir_to_exclude . | (cd /destination && tar xvf - )

Vous pouvez même utiliser cette technique à travers ssh.

0 votes

Cette approche entraîne inutilement le désencombrement de la source cible (et l'exclusion de certains répertoires de l'archive), puis le désencombrement de la cible. Cette approche n'est pas recommandée !

5 votes

@Waldheri vous avez tort. C'est la meilleure solution. Elle fait exactement ce que l'OP a demandé et elle fonctionne sur l'installation par défaut de la plupart des OS de type *nix. Le tarage et le détarage sont effectués à la volée sans artefact de système de fichiers (en mémoire), le coût de ce tar+untar est négligeable.

0 votes

@WouterDonders Tar est une surcharge minimale. Il n'applique pas de compression.

10voto

Dennis Williamson Points 105818

Vous pouvez utiliser find avec le -prune option.

Un exemple de man find :

       cd /source-dir
       find . -name .snapshot -prune -o \\( \\! -name \*~ -print0 \\)|
       cpio -pmd0 /dest-dir

       This command copies the contents of /source-dir to /dest-dir, but omits
       files  and directories named .snapshot (and anything in them).  It also
       omits files or directories whose name ends in ~,  but  not  their  con
       tents.  The construct -prune -o \\( ... -print0 \\) is quite common.  The
       idea here is that the expression before -prune matches things which are
       to  be  pruned.  However, the -prune action itself returns true, so the
       following -o ensures that the right hand side  is  evaluated  only  for
       those  directories  which didn't get pruned (the contents of the pruned
       directories are not even visited, so their  contents  are  irrelevant).
       The  expression on the right hand side of the -o is in parentheses only
       for clarity.  It emphasises that the -print0 action  takes  place  only
       for  things  that  didn't  have  -prune  applied  to them.  Because the
       default \`and' condition between tests binds more tightly than -o,  this
       is  the  default anyway, but the parentheses help to show what is going
       on.

0 votes

Bravo pour avoir trouvé un exemple très pertinent directement dans une page de manuel.

0 votes

C'est vraiment très beau ! Ceci est également disponible dans les documents en ligne . Malheureusement cpio n'a pas encore été empaqueté pour MSYS2.

3voto

ghostdog74 Points 86060

vous pouvez utiliser tar, avec l'option --exclude, et ensuite le désarchiver dans la destination. par exemple

cd /source_directory
tar cvf test.tar --exclude=dir_to_exclude *
mv test.tar /destination 
cd /destination  
tar xvf test.tar

voir la page de manuel de tar pour plus d'informations

2voto

Matthew Flaschen Points 131723

Similaire à l'idée de Jeff (non testée) :

find . -name * -print0 | grep -v "exclude" | xargs -0 -I {} cp -a {} destination/

0 votes

Désolé, mais je ne comprends vraiment pas pourquoi 5 personnes ont upvoted ceci quand il a été admis non testé et ne semble pas fonctionner sur un test simple : J'ai essayé ceci dans un sous-répertoire de /usr/share/icons et a immédiatement obtenu find: paths must precede expression: 22x22 où ce dernier est l'un des sous-répertoires qu'il contient. Ma commande était find . -name * -print0 | grep -v "scalable" | xargs -0 -I {} cp -a {} /z/test/ (il faut admettre que je suis sur MSYS2, donc vraiment en /mingw64/share/icons/Adwaita mais je ne vois pas en quoi c'est la faute de MSYS2).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X