Comment puis-je Tar un répertoire des fichiers et dossiers sans inclure le répertoire lui-même?

StackOverflow https://stackoverflow.com/questions/939982

  •  06-09-2019
  •  | 
  •  

Question

Je fais habituellement:

tar -czvf my_directory.tar.gz my_directory

Que faire si je veux juste inclure tout (y compris les fichiers cachés du système) dans my_directory, mais pas le répertoire lui-même? Je ne veux pas:

my_directory
   --- my_file
   --- my_file
   --- my_file

Je veux:

my_file
my_file
my_file
Était-ce utile?

La solution

cd my_directory/ && tar -zcvf ../my_dir.tgz . && cd - 

devrait faire le travail en une seule ligne. Il fonctionne bien pour les fichiers cachés ainsi. « * » Ne se développe pas les fichiers cachés par extension de nom de chemin au moins en bash. Voici mon expérience:

$ mkdir my_directory
$ touch my_directory/file1
$ touch my_directory/file2
$ touch my_directory/.hiddenfile1
$ touch my_directory/.hiddenfile2
$ cd my_directory/ && tar -zcvf ../my_dir.tgz . && cd ..
./
./file1
./file2
./.hiddenfile1
./.hiddenfile2
$ tar ztf my_dir.tgz
./
./file1
./file2
./.hiddenfile1
./.hiddenfile2

Autres conseils

Utilisez le commutateur -C de goudron:

tar -czvf my_directory.tar.gz -C my_directory .

Le -C my_directory dit goudron pour changer le répertoire courant my_directory, puis . signifie « ajouter le répertoire courant entier » (y compris les fichiers cachés et sous-répertoires).

Assurez-vous que vous faites -C my_directory avant de faire . ou bien vous obtiendrez les fichiers dans le répertoire courant.

Vous pouvez également créer une archive comme d'habitude et l'extraire avec:

tar --strip-components 1 -xvf my_directory.tar.gz

Jetez un oeil à --transform / --xform, il vous donne la possibilité de masser le nom de fichier que le fichier est ajouté à l'archive:

% mkdir my_directory
% touch my_directory/file1
% touch my_directory/file2
% touch my_directory/.hiddenfile1
% touch my_directory/.hiddenfile2
% tar -v -c -f my_dir.tgz --xform='s,my_directory/,,' $(find my_directory -type f)
my_directory/file2
my_directory/.hiddenfile1
my_directory/.hiddenfile2
my_directory/file1
% tar -t -f my_dir.tgz 
file2
.hiddenfile1
.hiddenfile2
file1

Transformer l'expression est similaire à celle de sed, et nous pouvons utiliser des séparateurs autres que / (, dans l'exemple ci-dessus).
https://www.gnu.org/software/tar/manual/html_section /tar_52.html

TL; DR

find /my/dir/ -printf "%P\n" | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -

Avec certaines conditions (archive uniquement les fichiers, répertoires et liens symboliques):

find /my/dir/ -printf "%P\n" -type f -o -type l -o -type d | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -

Explication

Le ci-dessous comprend malheureusement un répertoire parent ./ dans l'archive:

tar -czf mydir.tgz -C /my/dir .

Vous pouvez déplacer tous les fichiers sur ce répertoire en utilisant l'option de configuration --transform, mais cela ne se débarrasse pas du répertoire . lui-même. Il devient de plus en plus difficile à apprivoiser la commande.

Vous pouvez utiliser $(find ...) pour ajouter une liste de fichiers à la commande (comme dans magnus' réponse ), mais potentiellement provoque une erreur « liste des fichiers trop longtemps ». La meilleure façon est de le combiner avec l'option de -T de goudron, comme ceci:

find /my/dir/ -printf "%P\n" -type f -o -type l -o -type d | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -

En fait ce qu'il fait est la liste de tous les fichiers (-type f), des liens (-type l) et les sous-répertoires (-type d) sous votre répertoire, faire tous les noms de fichiers relatifs à l'aide -printf "%P\n", et passe ensuite que la commande tar (il prend les noms de fichiers de STDIN en utilisant -T -). L'option -C est nécessaire si le goudron sait où les fichiers avec des noms relatifs sont situés. Le drapeau de --no-recursion est donc que le goudron ne récursion pas dans des dossiers, il est dit d'archives (ce qui provoque les fichiers en double).

Si vous avez besoin de faire quelque chose de spécial avec les noms de fichiers (filtrage, etc.) suivant les liens symboliques, la commande find est assez puissant, et vous pouvez le tester en tout enlever la partie tar de la commande ci-dessus:

$ find /my/dir/ -printf "%P\n" -type f -o -type l -o -type d
> textfile.txt
> documentation.pdf
> subfolder2
> subfolder
> subfolder/.gitignore

Par exemple, si vous souhaitez filtrer les fichiers PDF, ajouter ! -name '*.pdf'

$ find /my/dir/ -printf "%P\n" -type f ! -name '*.pdf' -o -type l -o -type d
> textfile.txt
> subfolder2
> subfolder
> subfolder/.gitignore

Non GNU find

La commande utilise printf (disponible dans GNU find) qui indique find d'imprimer ses résultats avec des chemins relatifs. Toutefois, si vous n'avez pas GNU find, cela fonctionne pour rendre les chemins relatifs (supprime les parents avec sed):

find /my/dir/ -type f -o -type l -o -type d | sed s,^/my/dir/,, | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -

Cette réponse devrait fonctionner dans la plupart des situations. Notez cependant comment les noms de fichiers sont stockés dans le fichier tar comme, par exemple, ./file1 plutôt que file1. Je trouve que cela a causé des problèmes lors de l'utilisation de cette méthode pour manipuler les tarballs utilisés comme des paquets dans BuildRoot .

Une solution consiste à utiliser des Bash globs à la liste tous les fichiers sauf pour .. comme ceci:

tar -C my_dir -zcvf my_dir.tar.gz .[^.]* ..?* *

Ceci est un truc que j'appris de cette réponse .

goudron renvoie une erreur s'il n'y a pas de fichiers correspondant à ..?* ou .[^.]*, mais il faudra encore travailler. Si l'erreur est un problème (vous vérifiez la réussite dans un script), cela fonctionne:

shopt -s nullglob
tar -C my_dir -zcvf my_dir.tar.gz .[^.]* ..?* *
shopt -u nullglob

Bien que maintenant nous jouer avec les options du shell, nous pourrions décider qu'il est plus propre d'avoir * correspondance les fichiers cachés:

shopt -s dotglob
tar -C my_dir -zcvf my_dir.tar.gz *
shopt -u dotglob

Cela pourrait ne pas fonctionner lorsque votre shell globs * dans le répertoire courant, donc encore, utilisez:

shopt -s dotglob
cd my_dir
tar -zcvf ../my_dir.tar.gz *
cd ..
shopt -u dotglob
cd my_directory
tar zcvf ../my_directory.tar.gz *

Si c'est un système Unix / Linux, et vous vous souciez des fichiers cachés (qui ne sera pas atteint *), vous devez faire:

cd my_directory
tar zcvf ../my_directory.tar.gz * .??*

Je ne sais pas ce que les fichiers cachés ressemblent sous Windows.

Je propose la fonction bash suivante (premier argument est le chemin d'accès au répertoire, second argument est le nom de base de l'archive résultante):

function tar_dir_contents ()
{
    local DIRPATH="$1"
    local TARARCH="$2.tar.gz"
    local ORGIFS="$IFS"
    IFS=$'\n'
    tar -C "$DIRPATH" -czf "$TARARCH" $( ls -a "$DIRPATH" | grep -v '\(^\.$\)\|\(^\.\.$\)' )
    IFS="$ORGIFS"
}

Vous pouvez l'exécuter ainsi:

$ tar_dir_contents /path/to/some/dir my_archive

et il va générer l'archive my_archive.tar.gz existant dans le répertoire en cours. Il fonctionne avec caché (. *) Et des éléments avec des éléments avec des espaces dans leur nom.

cd my_directory && tar -czvf ../my_directory.tar.gz $(ls -A) && cd ..

Celui-ci a fonctionné pour moi et il est inclure tous les fichiers cachés sans mettre tous les fichiers dans un répertoire racine nommé « » comme dans la réponse de Tomoe :

Utilisez pax.

Pax est un paquet mais désapprouvée fait le travail parfaitement et de façon simple.

pax -w > mydir.tar mydir

façon plus simple que je trouve:

cd my_dir && tar -czvf ../my_dir.tar.gz *

# tar all files within and deeper in a given directory
# with no prefixes ( neither <directory>/ nor ./ )
# parameters: <source directory> <target archive file>
function tar_all_in_dir {
    { cd "$1" && find -type f -print0; } \
    | cut --zero-terminated --characters=3- \
    | tar --create --file="$2" --directory="$1" --null --files-from=-
}

poignées en toute sécurité avec des espaces ou des noms de fichiers d'autres caractères inhabituels. Vous pouvez aussi ajouter un -name '*.sql' ou un filtre similaire à la commande find pour limiter les fichiers inclus.

 tar -cvzf  tarlearn.tar.gz --remove-files mytemp/*

Si le dossier est MonTemp alors si vous appliquez le précède, il zip et supprimer tous les fichiers dans le dossier, mais le laisser seul

 tar -cvzf  tarlearn.tar.gz --remove-files --exclude='*12_2008*' --no-recursion mytemp/*

Vous pouvez donner les motifs d'exclusion et de préciser également de ne pas regarder dans les sous-dossiers trop

tar -C my_dir -zcvf my_dir.tar.gz `ls my_dir`
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top