J'ai cette ligne très simple dans un script bash qui s'exécute avec succès (c.-à-d. Produisant le file _data.tar
), excepté qu'elle n'exclut pas les sous-directorys --exclude
on dit exclure via l'option --exclude
:
/bin/tar -cf /home/_data.tar --exclude='/data/sub1/*' --exclude='/data/sub2/*' --exclude='/data/sub3/*' --exclude='/data/sub4/*' --exclude='/data/sub5/*' /data
Au lieu de cela, il produit un file _data.tar
qui contient tout sous / data, y compris les files dans les sous-directorys que je voulais exclure.
Une idée pourquoi? et comment résoudre ce problème?
Mise à jour J'ai implémenté mes observations en fonction du lien fourni dans la première réponse ci-dessous (premier niveau dir, pas d'espace après la dernière exclusion):
/bin/tar -cf /home/_data.tar /data --exclude='/data/sub1/*' --exclude='/data/sub2/*' --exclude='/data/sub3/*' --exclude='/data/sub4/*' --exclude='/data/sub5/*'
Mais cela n'a pas aidé. Tous les sous-directorys "exclus" sont présents dans le file _data.tar
résultant.
C'est déroutant. Qu'il s'agisse d'un bogue dans le tar actuel (GNU tar 1.23, sur un CentOS 6.2, Linux 2.6.32) ou de «sensibilité extrême» du tar sur les espaces blancs et autres fautes de frappe faciles à percevoir, je considère cela comme un bug. Pour l'instant.
C'est horrible : j'ai essayé la perspicacité suggérée ci-dessous (pas de fuite /*
) et cela ne fonctionne toujours pas dans le script de production:
/bin/tar -cf /home/_data.tar /data --exclude='/data/sub1' --exclude='/data/sub2' --exclude='/data/sub3' --exclude='/data/sub4'
Je ne vois aucune différence entre ce que j'ai essayé et ce que @Richard Perrin a essayé, à l'exception des guillemets et de 2 espaces au lieu de 1. Je vais essayer ceci (je dois attendre que le script du soir s'exécute comme directory à sauvegarder up est énorme) et rendre count.
/bin/tar -cf /home/_data.tar /data --exclude=/data/sub1 --exclude=/data/sub2 --exclude=/data/sub3 --exclude=/data/sub4
Je commence à penser que toutes ces sensibilités de tar --exclude
pas le goudron mais quelque chose dans mon environnement, mais alors qu'est-ce que cela pourrait être?
Ça a marché! La dernière variante essayée (pas de guillemets simples et d'espace unique au lieu d'un double-espace entre les --exclude
) testé fonctionne. Bizarre mais acceptant.
Incroyable! Il s'avère qu'une ancienne version de tar
(1.15.1) n'exclurait que si le directory de niveau supérieur était le dernier sur la command line. C'est exactement le contraire de la version 1.23. Pour info.
Si vous souhaitez exclure un directory entier, votre model doit correspondre à ce directory, et non aux files qu'il contient. Utilisez --exclude=/data/sub1
au lieu de --exclude='/data/sub1/*'
Soyez prudent en citant les motifs pour les protéger de l'expansion de la coquille.
Voir cet exemple, avec des problèmes dans l'appel final:
$ for i in 0 1 2; do mkdir -p /tmp/data/sub$i; echo foo > /tmp/data/sub$i/foo; done $ find /tmp/data /tmp/data /tmp/data/sub2 /tmp/data/sub2/foo /tmp/data/sub0 /tmp/data/sub0/foo /tmp/data/sub1 /tmp/data/sub1/foo $ tar -zvcf /tmp/_data.tar /tmp/data --exclude='/tmp/data/sub[1-2]' tar: Removing leading `/' from member names /tmp/data/ /tmp/data/sub0/ /tmp/data/sub0/foo $ tar -zvcf /tmp/_data.tar /tmp/data --exclude=/tmp/data/sub[1-2] tar: Removing leading `/' from member names /tmp/data/ /tmp/data/sub0/ /tmp/data/sub0/foo $ echo tar -zvcf /tmp/_data.tar /tmp/data --exclude=/tmp/data/sub[1-2] tar -zvcf /tmp/_data.tar /tmp/data --exclude=/tmp/data/sub[1-2] $ tar -zvcf /tmp/_data.tar /tmp/data --exclude /tmp/data/sub[1-2] tar: Removing leading `/' from member names /tmp/data/ /tmp/data/sub2/ /tmp/data/sub2/foo /tmp/data/sub0/ /tmp/data/sub0/foo /tmp/data/sub2/ tar: Removing leading `/' from hard link targets /tmp/data/sub2/foo $ echo tar -zvcf /tmp/_data.tar /tmp/data --exclude /tmp/data/sub[1-2] tar -zvcf /tmp/_data.tar /tmp/data --exclude /tmp/data/sub1 /tmp/data/sub2
Il se peut que votre version de tar
nécessite que les options --exclude
soient placées au début de la command tar
.
Voir: https://stackoverflow.com/q/984204
tar --exclude='./folder' --exclude='./upload/folder2' \ -zcvf /backup/filename.tgz .
Voir: http://mandrivausers.org/index.php?/topic/8585-multiple-exclude-in-tar/
tar --exclude=<first> --exclude=<second> -cjf backupfile.bz2 /home/*
Alternative:
EXCLD='first second third' tar -X <(for i in ${EXCLD}; do echo $i; done) -cjf backupfile.bz2 /home/*
Encore une autre astuce de command tar
est d' ici :
tar cvfz myproject.tgz --exclude='path/dir_to_exclude1' \ --exclude='path/dir_to_exclude2' myproject
Pour exclure plusieurs files, essayez
--exclude=/data/{sub1,sub2,sub3,sub4}
Cela permettra d'économiser du code et des maux de tête. Ceci est une solution globale, pour tous les types de programmes / options. Si vous souhaitez également inclure le directory parent dans votre sélection (dans ce cas, datatables), vous devez inclure une virgule de fin. Par exemple:
umount /data/{sub1,sub2,}
Ce lien pourrait être utile. http://answers.google.com/answers/threadview/id/739467.html
Deux différences immédiates entre la ligne de non-travail et quelques conseils dans le lien:
--exclude
. Une solution de contournement peut être d'utiliser une combinaison de find ... -prune
et tar
pour exclure les directorys spécifiés.
Sur Mac OS X, l'option --exclude
de GNU tar
semble fonctionner comme il se doit.
Dans le cas de test suivant, les directorys /private/var/log/asl
et /private/var/log/DiagnosticMessages
doivent être exclus d'une archive compressée du directory /private/var/log
.
# all successfully tested in Bash shell on Mac OS X (using gnutar and gfind) # sudo port install findutils # for gfind from MacPorts sudo gnutar -czf ~/Desktop/varlog.tar.gz /private/var/log --exclude "/private/var/log/asl" --exclude "/private/var/log/DiagnosticMessages" sudo gnutar -czf ~/Desktop/varlog.tar.gz --exclude "/private/var/log/asl" --exclude "/private/var/log/DiagnosticMessages" /private/var/log set -f # disable file name globbing sudo gnutar -czf ~/Desktop/varlog.tar.gz --exclude "/private/var/log/asl" --exclude "/private/var/log/Diagnostic*" /private/var/log # combining GNU find and tar (on Mac OS X) sudo gfind /private/var/log -xdev -type d \( -name "asl" -o -name "DiagnosticMessages" \) -prune -o -print0 | sudo gnutar --null --no-recursion -czf ~/Desktop/varlog.tar.gz --files-from - # exclude even more dirs sudo gfind /private/var/log -xdev -type d \( -name "asl" -o -name "[Dacfks]*" \) -prune -o -print0 | sudo gnutar --null --no-recursion -czf ~/Desktop/varlog.tar.gz --files-from - # testing the compressed archive gnutar -C ~/Desktop -xzf ~/Desktop/varlog.tar.gz sudo gfind /private/var/log ~/Desktop/private \( -iname DiagnosticMessages -or -iname asl \) sudo rm -rf ~/Desktop/varlog.tar.gz ~/Desktop/private
Peut-être que vous pouvez essayer la command avec une autre option:
--wildcards
Et vérifiez s'il fonctionne comme prévu.
J'utilise un mac, et a constaté que les excludes ne fonctionnaient pas sauf si le dossier de niveau supérieur est le dernier argument
exemple de command de travail:
tar czvf tar.tgz --exclude='Music' dir
Pour information:
$: tar --version bsdtar 2.8.3 - libarchive 2.8.3
Dans mon cas, cela n'a pas exclu pour une raison différente.
Le path complet par rapport au path relatif.
Le directory d'exclusion et le directory doivent utiliser le même format de path (c'est-à-dire le path complet ou les deux paths relatifs)
Exemple:
tar -cvf ctms-db-sync.tar --exclude='/home/mine/tmp/ctms-db-sync/sql' ctms-db-sync
Cela ne fonctionnera pas car exclure utilise le path complet où la cible utilise un path relatif
tar -cvf ctms-db-sync.tar --exclude='/home/mine/tmp/ctms-db-sync/sql' /home/mine/tmp/ctms-db-sync
Cela fonctionne parce que les deux utilisent le path complet
tar -cvf ctms-db-sync.tar --exclude='ctms-db-sync/sql' ctms-db-sync
Cela fonctionne parce que les deux utilisent le path relatif
Au lieu de --exclude=
utiliser -X
avec un file text:
http://www.cyberciti.biz/faq/exclude-certain-files-when-creating-a-tarball-using-tar-command/
Notes supplémentaires à l'excellente réponse de R Perrin :
Supposons que vous ne souhaitiez pas archiver les paths absolus mais relatifs, par exemple 'data' au lieu de '/ tmp / data'. Pour exclure les paths absolus, vos arguments tar seront différents en fonction de l'implémentation tar (gnu tar vs. bsd tar) que vous utilisez:
$ for i in 0 1 2; do for j in 0 1 2; do mkdir -p /tmp/data/sub$i/sub$j echo foo > /tmp/data/sub$i/sub$j/foo done done $ find /tmp/data/ /tmp/data/ /tmp/data/sub2 /tmp/data/sub2/sub2 /tmp/data/sub2/sub2/foo /tmp/data/sub2/sub1 /tmp/data/sub2/sub1/foo /tmp/data/sub2/sub0 /tmp/data/sub2/sub0/foo /tmp/data/sub1 /tmp/data/sub1/sub2 /tmp/data/sub1/sub2/foo /tmp/data/sub1/sub1 /tmp/data/sub1/sub1/foo /tmp/data/sub1/sub0 /tmp/data/sub1/sub0/foo /tmp/data/sub0 /tmp/data/sub0/sub2 /tmp/data/sub0/sub2/foo /tmp/data/sub0/sub1 /tmp/data/sub0/sub1/foo /tmp/data/sub0/sub0 /tmp/data/sub0/sub0/foo $ cd /tmp/data; tar -zvcf /tmp/_data.tar --exclude './sub[1-2]' ./ ./sub0/ ./sub0/sub2/ ./sub0/sub2/foo ./sub0/sub1/ ./sub0/sub1/foo ./sub0/sub0/ ./sub0/sub0/foo # ATTENTION: bsdtar's behaviour differs from traditional tar (without a leading '^')! $ cd /tmp/data; bsdtar -zvcf /tmp/_data.tar --exclude './sub[1-2]' . a . a ./sub0 a ./sub0/sub0 a ./sub0/sub0/foo # FIX: Use a regex by adding a leading '^' will cause bsdtar to match only parent files and folders. $ cd /tmp/data; bsdtar -zvcf /tmp/_data.tar --exclude '^./sub[1-2]' . # ALTERNATIVE: bsdtar -C /tmp/data -zvcf /tmp/_data.tar --exclude '^./sub[1-2]' . a . a ./sub0 a ./sub0/sub2 a ./sub0/sub1 a ./sub0/sub0 a ./sub0/sub0/foo a ./sub0/sub1/foo a ./sub0/sub2/foo