Comment puis-je tar un répertoire de fichiers et de dossiers sans inclure le répertoire lui-même?
Je fais généralement:
tar -czvf my_directory.tar.gz my_directory
Que faire si je veux juste inclure tout (y compris les fichiers système cachés) 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
15 réponses
cd my_directory/ && tar -zcvf ../my_dir.tgz . && cd -
Devrait faire le travail en une seule ligne. Il fonctionne bien pour les fichiers masqués. "*"ne développe pas les fichiers cachés par l'expansion du nom de chemin au moins dans 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
Utilisez le commutateur -C
de tar:
tar -czvf my_directory.tar.gz -C my_directory .
Le -C my_directory
indique à tar de changer le répertoire courant en my_directory
, puis .
signifie "ajouter le répertoire courant entier" (y compris les fichiers cachés et les sous-répertoires).
Assurez-vous de faire -C my_directory
avant de faire .
sinon vous obtiendrez les fichiers dans le répertoire courant.
Vous pouvez aussi 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 du 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 d'autres que /
(,
dans l'exemple ci-dessus).
https://www.gnu.org/software/tar/manual/html_section/tar_52.html
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 simplement file1
. J'ai trouvé que cela causait des problèmes lors de l'utilisation de cette méthode pour manipuler les tarballs utilisés comme Fichiers de package dans BuildRoot.
Une solution consiste à utiliser des globs Bash pour lister tous les fichiers sauf ..
comme ceci:
tar -C my_dir -zcvf my_dir.tar.gz .[^.]* ..?* *
C'est un truc que j'ai appris de cette réponse.
Maintenant tar va renvoie une erreur s'il n'y a pas de fichiers correspondant à ..?*
ou .[^.]*
, mais cela fonctionnera toujours. Si l'erreur est un problème (vous vérifiez le succès d'un script), cela fonctionne:
shopt -s nullglob
tar -C my_dir -zcvf my_dir.tar.gz .[^.]* ..?* *
shopt -u nullglob
Bien que maintenant nous soyons en train de jouer avec les options du shell, nous pourrions décider qu'il est plus propre d'avoir *
match hidden files:
shopt -s dotglob
tar -C my_dir -zcvf my_dir.tar.gz *
shopt -u dotglob
Cela peut ne pas fonctionner où vos globs shell *
dans le répertoire courant, donc alternativement, utilisez:
shopt -s dotglob
cd my_dir
tar -zcvf ../my_dir.tar.gz *
cd ..
shopt -u dotglob
TL; DR
find /my/dir/ -printf "%P\n" | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -
Avec certaines conditions (archiver uniquement les fichiers, dirs 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
Ce qui suit inclut malheureusement un répertoire parent ./
dans l'archive:
tar -czf mydir.tgz -C /my/dir .
Vous pouvez déplacer tous les fichiers hors de ce répertoire en utilisant l'option de configuration --transform
, mais cela ne supprime pas le répertoire .
lui-même. Il devient de plus en plus difficile d'apprivoiser la commande.
Vous pouvez utiliser $(find ...)
pour ajouter une liste de commande (comme dans la réponse de magnus), mais cela provoque potentiellement une erreur "Liste de fichiers trop longue". Le meilleur moyen est de le combiner avec l'option -T
de tar, 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 -
Fondamentalement, il répertorie tous les fichiers (-type f
), les liens (-type l
) et les sous-répertoires (-type d
) sous votre répertoire, rend tous les noms de fichiers relatifs en utilisant -printf "%P\n"
, puis passe cela à la commande tar (il prend les noms de fichiers de STDIN en utilisant -T -
). L'option -C
est nécessaire pour que tar sache où les fichiers avec les noms relatifs sont localisés. L'indicateur --no-recursion
est tel que tar ne se recurse pas dans les dossiers qu'il est dit d'archiver (provoquant des fichiers en double).
Si vous avez besoin de faire quelque chose de spécial avec les noms de fichiers (filtrage, liens symboliques suivants, etc.), la commande find
est assez puissante, et vous pouvez la tester en supprimant simplement 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, ajoutez ! -name '*.pdf'
$ find /my/dir/ -printf "%P\n" -type f ! -name '*.pdf' -o -type l -o -type d
> textfile.txt
> subfolder2
> subfolder
> subfolder/.gitignore
Recherche Non GNU
La commande utilise printf
(disponible dans GNU find
) qui indique à find
d'imprimer ses résultats avec des chemins relatifs. Cependant, 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 -
Si C'est un système Unix / Linux, et que vous vous souciez des fichiers cachés (qui seront manqués par*), vous devez faire:
cd my_directory
tar zcvf ../my_directory.tar.gz * .??*
Je ne sais pas à quoi ressemblent les fichiers cachés sous Windows.
Je proposerais la fonction Bash suivante (le premier argument est le chemin d'accès au répertoire, le deuxième 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 de cette façon:
$ tar_dir_contents /path/to/some/dir my_archive
Et il va générer l'archive my_archive.tar.gz
dans le répertoire courant. Il fonctionne avec caché (.* ) éléments et avec des éléments avec des espaces dans leur nom de fichier.
Utilisez pax.
Pax est un paquet obsolète mais fait le travail parfaitement et d'une manière simple.
pax -w > mydir.tar mydir
find $TARGET_DIR -maxdepth 1 -type f -print0 \
| xargs --null --max-args 1 basename --zero \
| tar --create --file=result.tar --directory=$TARGET_DIR --null --files-from=-
Suppose que vous ne voulez pas inclure de sous-répertoires ou de fichiers à partir de sous-répertoires. Gère en toute sécurité les noms de fichiers avec des espaces ou d'autres caractères inhabituels. Vous pouvez éventuellement ajouter un -name '*.sql'
ou un filtre similaire à la commande find pour limiter les fichiers inclus.
Moyen le plus simple que j'ai trouvé:
Cd my_dir && tar-czvf ../ my_dir.tar.gz *
tar -cvzf tarlearn.tar.gz --remove-files mytemp/*
Si le dossier est mytemp, alors si vous appliquez ce qui précède, il compressera et supprimera tous les fichiers du dossier mais le laissera seul
tar -cvzf tarlearn.tar.gz --remove-files --exclude='*12_2008*' --no-recursion mytemp/*
Vous pouvez donner des motifs d'exclusion et également spécifier de ne pas regarder dans les sous-dossiers aussi