Tar un répertoire, mais ne stockez pas les chemins absolus complets dans l'archive

277

J'ai la commande suivante dans la partie d'un script shell de sauvegarde:

tar -cjf site1.bz2 /var/www/site1/

Lorsque j'énumère le contenu de l'archive, j'obtiens:

tar -tf site1.bz2
var/www/site1/style.css
var/www/site1/index.html
var/www/site1/page2.html
var/www/site1/page3.html
var/www/site1/images/img1.png
var/www/site1/images/img2.png
var/www/site1/subdir/index.html

Mais je voudrais supprimer la partie /var/www/site1du répertoire et des noms de fichiers dans l'archive, afin de simplifier l'extraction et d'éviter une structure de répertoire constante inutile. Je ne sais jamais, au cas où j'extraireais des sites Web sauvegardés dans un endroit où les données Web n'étaient pas stockées /var/www.

Pour l'exemple ci-dessus, j'aimerais avoir:

tar -tf site1.bz2
style.css
index.html
page2.html
page3.html
images/img1.png
images/img2.png
subdir/index.html

Ainsi, lorsque je procède à l'extraction, les fichiers sont extraits dans le répertoire courant et je n'ai pas besoin de déplacer les fichiers extraits par la suite, de sorte que les structures de sous-répertoires soient préservées.

Il y a déjà beaucoup de questions sur tar et la sauvegarde dans stackoverflowet à d'autres endroits sur le web, mais la plupart d'entre eux demandent de supprimer toute la structure du sous-répertoire (aplatissement), ou simplement d'ajouter ou de supprimer l'initiale / dans les noms (je ne ' je ne sais pas ce qu'il change exactement lors de l'extraction), mais pas plus.

Après avoir lu certaines des solutions trouvées ici et là ainsi que le manuel, j'ai essayé:

tar -cjf site1.bz2 -C . /var/www/site1/
tar -cjf site1.bz2 -C / /var/www/site1/
tar -cjf site1.bz2 -C /var/www/site1/ /var/www/site1/
tar -cjf site1.bz2 --strip-components=3 /var/www/site1/

Mais aucun d'eux n'a fonctionné comme je le souhaite. Certains ne font rien, d'autres n'archivent plus de sous-répertoires.

C'est à l'intérieur d'un script shell de sauvegarde lancé par un Cron, donc je ne sais pas bien, quel utilisateur l'exécute, quel est le chemin et le répertoire courant, donc toujours écrire un chemin absolu est requis pour tout, et je préférerais ne pas changer le répertoire actuel pour éviter de casser quelque chose de plus dans le script (car il sauvegarde non seulement les sites Web, mais aussi les bases de données, puis envoie tout cela sur FTP, etc.)

Comment y parvenir?

Ai-je juste mal compris le fonctionnement de l'option -C?

QuentinC
la source
connexes: unix.stackexchange.com/questions/22842/tar-with-relative-paths | serverfault.com/questions/339762/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
Eh bien, -Csignifie simplement "changer de répertoire", tout en remplaçant un chemin (ou préfixe) ne peut être fait que par --transform. rif. superuser.com/questions/595510/prepend-prefix-in-tar/595512 vous pouvez simplement -C (changer de répertoire) et --transformer: `` `tar cjf site1.bz2 --transform" s / ^ \. \ // $ targetbase / "-C / var / www / site1. ``
Daniele Cruciani
C'est une très bonne question et malheureusement aucune des réponses à cette date n'est satisfaisante. Nous n'avons pas encore entendu de personne sage comment nous pourrions éventuellement extraire le seul fichier style.css (exemple ci-dessus) dans le répertoire actuel sans aucune référence à l'emplacement d'origine ou à l'arborescence du répertoire? Je ne veux pas encombrer mon répertoire actuel avec une nouvelle arborescence indésirable. Cela ressemble à une grave lacune de tarball qui a été ignorée pendant des années.
elmclose

Réponses:

383
tar -cjf site1.tar.bz2 -C /var/www/site1 .

Dans l'exemple ci-dessus, tar changera de répertoire /var/www/site1avant de faire son travail car l'option a -C /var/www/site1été donnée.

De man tar:

OTHER OPTIONS

  -C, --directory DIR
       change to directory DIR
Lars Brinkhoff
la source
152
Ne manquez pas le point à la fin, c'est important ;-)
Freedom_Ben
9
que diriez-vous si vous souhaitez également sélectionner les fichiers à sauvegarder en fonction d'un caractère générique? -C / var / www / site1 * .dat ne fonctionne pas :(
Andy Lorenz
16
Le point indique tard'archiver tout dans le répertoire courant. Et -Cdéfinit le répertoire courant.
Lars Brinkhoff,
21
Cela fonctionne très bien. Je trouve utile de conserver le nom du répertoire (mais pas le chemin complet), j'ai donc fait ce qui suit: tar -czvf site1.tar.gz -C /var/www/ site1(Notez l'espace, j'utilise toujours le -C, pour passer au répertoire parent et en spécifiant le répertoire à tar au lieu de point)
jorfus
9
J'obtiens un premier point sur le chemin du goudron, par exemple, ./folderscomment le supprimer?
Mika571
39

L'option -Cfonctionne; juste pour clarification, je posterai 2 exemples:

  1. création d'un tarball sans le chemin complet: chemin complet /home/testuser/workspace/project/application.waret ce que nous voulons est juste project/application.warainsi:

    tar -cvf output_filename.tar  -C /home/testuser/workspace project

    Remarque: il y a un espace entre workspaceet project; tar remplacera le chemin complet par juste project.

  2. extraction de l'archive tar avec changement du chemin cible (par défaut ., c'est- à -dire le répertoire courant)

    tar -xvf output_filename.tar -C /home/deploy/

    tarextraira l'archive tar en fonction du chemin donné et en préservant le chemin de création; dans notre exemple, le fichier application.warsera extrait vers /home/deploy/project/application.war.

    /home/deploy: donnée sur l'extrait
    project: donnée sur la création de l'archive tar

Remarque: si vous souhaitez placer l'archive tar créée dans un répertoire cible, il vous suffit d'ajouter le chemin cible avant le nom de l'archive tar. par exemple:

tar -cvf /path/to/place/output_filename.tar  -C /home/testuser/workspace project
Grizli
la source
1
comment ajouter un caractère générique pour la sélection de fichiers dans le dernier exemple?
Siva
Le problème avec les caractères génériques est que le shell les étend aux noms de fichiers correspondants et que tar ne les développe pas s'ils sont cités ...
Gert van den Berg
J'ai essayé cela sur Ubuntu 18.04 et pas de chance. Je ne suis pas sûr de ce qui me manque. Ma sortie standard l'affiche correctement lorsque je l'emballe, mais quand je la décompresse, elle a toujours le chemin complet
sdc
14

Il semble que l' -Coption jusqu'à tar v2.8.3 ne fonctionne pas de manière cohérente sur toutes les plates-formes (OS). -CL'option est censée ajouter un répertoire à l'archive mais sur Mac et Ubuntu, elle ajoute un préfixe de chemin absolu dans le fichier tar.gz généré.

tar target_path/file.tar.gz -C source_path/source_dir

Par conséquent, la solution cohérente et robuste consiste à cdentrer dans source_path (répertoire parent de source_dir) et à exécuter

tar target_path/file.tar.gz source_dir

ou

tar -cf target_path/file.tar.gz source_dir

dans votre script. Cela supprimera le préfixe de chemin absolu dans la structure de répertoires de votre fichier tar.gz généré.

Chinthaka Senanayaka
la source
1
L'utilisation de l'option -C DID supprime les préfixes de chemin absolus à l'intérieur du fichier tar.gz généré sur fedora 29. Votre réponse est-elle spécifique à un système?
EL_DON
@EL_DON: Je n'ai pas testé l'option -C sur Fedora, mais idéalement, le logiciel d'application tar devrait fonctionner de manière cohérente sur chaque plate-forme, sauf s'il s'agit d'un bogue dans l'application tar. -Option, j'ai testé sur Mac 10.8 et Mac 10.13 et Ubuntu (version dont je ne me souviens plus). Mais à partir de tar v2.8.3, la commande a été modifiée en tar -cf target_path / file.tar.gz source_dir et toujours si vous ajoutez l'option -C, elle ne supprimera pas le préfixe de chemin absolu dans le fichier tar.gz généré.
Chinthaka Senanayaka
J'ai testé à nouveau sur un système centOS. Après avoir créé tous les chemins dans l'exemple et exécuté la commande (avec -cvfajouté après tar), je trouve que le fichier tar.gz résultant n'a pas de chemins absolus à l'intérieur, ce qui est cohérent avec plusieurs autres réponses. Si vous pensez que tar est cassé ou obsolète sur les deux systèmes que j'ai utilisés pour les tests, veuillez créer un lien vers une documentation qui soutiendrait votre réponse. Je pense que l' -Coption change de répertoire avant de s'exécuter (comme dans les autres réponses). Lorsque je l'omet, tar essaie d'ajouter des fichiers indésirables à partir de ./, y compris les chemins à partir de ./.
EL_DON
J'ai utilisé ce document: linux.die.net/man/1/tar Oui, le document dit que -C ferait le changement de chemin, mais sur mon Mac 10.13 cela ne fonctionne pas. cela peut être un comportement incohérent de l'application tar. Cela signifie que c'est un bug. Si vous écrivez un script shell pour qu'il s'exécute sur toutes les plates-formes Unix, il vaut mieux être sûr d'utiliser du code qui fonctionnera sur tous les systèmes d'exploitation.
Chinthaka Senanayaka
Votre réponse ne dit pas qu'il peut y avoir un bogue et la solution la plus robuste pour la compatibilité multiplateforme est d' cdabord. Votre réponse dit que l'outil fonctionne de la manière opposée de la façon dont les documents disent qu'il fonctionne et comment il fonctionne sur mon système, donc c'est une mauvaise réponse. Vous pouvez facilement le réparer.
EL_DON
7

La commande suivante créera un répertoire racine "." et y mettre tous les fichiers du répertoire spécifié.

tar -cjf site1.tar.bz2 -C /var/www/site1 .

Si vous voulez mettre tous les fichiers à la racine du fichier tar, @chinthaka a raison. Entrez simplement dans le répertoire et faites:

tar -cjf target_path/file.tar.gz *

Cela mettra tous les fichiers du cwd dans le fichier tar en tant que fichiers racine.

WLatif
la source
1
L'utilisation de * ne sauvegarde aucun fichier ou fichier "caché". (fyi, l'utilisation de -C avec * échoue, le shell étend le
répertoire
1

L'utilisation du "point" conduit à la création d'un dossier nommé "point" (sur Ubuntu 16).

tar -tf site1.bz2 -C /var/www/site1/ .

J'ai traité cela plus en détail et préparé un exemple. Enregistrement sur plusieurs lignes, plus une exception.

tar -tf site1.bz2\
    -C /var/www/site1/ style.css\
    -C /var/www/site1/ index.html\
    -C /var/www/site1/ page2.html\
    -C /var/www/site1/ page3.html\
    --exclude=images/*.zip\
    -C /var/www/site1/ images/
    -C /var/www/site1/ subdir/
/
Sergey Asachev
la source
Pourquoi appelez-vous cela "point"? C'est juste ., qui est le répertoire courant. Dans le contexte de la tar.gzstructure de, c'est juste le niveau de base / racine / supérieur, non?
EL_DON
Voir l'image instantanée pour les détails de l' image . Ma voie est plus correcte à utiliser, c'est mon avis.
Sergey Asachev
0

Si vous souhaitez archiver un sous-répertoire et couper le chemin du sous-répertoire, cette commande sera utile:

tar -cjf site1.bz2 -C /var/www/ site1
Hirurg103
la source