Je fais typiquement:
tar -czvf my_directory.tar.gz my_directory
Que se passe-t-il si je veux simplement tout inclure (y compris tous 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 voudrais:
my_file
my_file
my_file
cd my_directory/ && tar -zcvf ../my_dir.tgz . && cd -
devrait faire le travail en une seule ligne. Cela fonctionne aussi bien pour les fichiers cachés. "*" ne développe pas les fichiers cachés par extension de nom de chemin au moins en bash. Ci-dessous 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 .
-C my_directory
indique à tar de changer le répertoire en cours en my_directory
, puis .
signifie "ajouter le répertoire en cours entier" (y compris les fichiers cachés et les sous-répertoires).
Assurez-vous de bien faire -C my_directory
avant de faire .
sinon vous aurez les fichiers dans le répertoire actuel.
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
, cela vous donne l'occasion de modifier le nom du fichier lorsque celui-ci 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
L'expression de transformation 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
find /my/dir/ -printf "%P\n" | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -
Avec certaines conditions (archiver 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 -
La liste ci-dessous 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 fichiers à la commande (comme dans réponse de magnus ), mais cela peut entraîner 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 -
En gros, il répertorie tous les fichiers (-type f
), les liens (-type l
) et les sous-répertoires (-type d
) de votre répertoire, rend tous les noms de fichiers relatifs à l'aide de -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ù sont situés les fichiers portant des noms relatifs. Le drapeau --no-recursion
évite que tar ne rentre dans les dossiers qu’il est ordonné d’archiver (ce qui entraîne la duplication de fichiers).
Si vous avez besoin de faire quelque chose de spécial avec les noms de fichiers (filtrage, liens symboliques, etc.), la commande find
est assez puissante et vous pouvez le 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
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 rend 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, par exemple ./file1
plutôt que simplement file1
. J'ai constaté que cela posait des problèmes lors de l'utilisation de cette méthode pour manipuler des archives contenant des paquets utilisés dans BuildRoot .
Une solution consiste à utiliser certains globs Bash pour répertorier tous les fichiers à l'exception de ..
comme ceci:
tar -C my_dir -zcvf my_dir.tar.gz .[^.]* ..?* *
C’est un tour que j’ai appris de cette réponse .
Maintenant, tar renverra une erreur s'il n'y a pas de fichiers correspondant à ..?*
ou .[^.]*
, mais cela fonctionnera toujours. Si l'erreur pose un problème (vous vérifiez le succès dans un script), cela fonctionne:
shopt -s nullglob
tar -C my_dir -zcvf my_dir.tar.gz .[^.]* ..?* *
shopt -u nullglob
Bien que nous modifions maintenant les options de Shell, nous pourrions décider qu'il est préférable de faire correspondre *
aux fichiers cachés:
shopt -s dotglob
tar -C my_dir -zcvf my_dir.tar.gz *
shopt -u dotglob
Cela pourrait ne pas fonctionner là où votre shell globs *
dans le répertoire en cours, alors utilisez alternativement:
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 *
S'il s'agit d'un système Unix/Linux et que vous vous souciez des fichiers cachés (ce qui manquera par *), vous devez procéder comme suit:
cd my_directory
tar zcvf ../my_directory.tar.gz * .??*
Je ne sais pas à quoi ressemblent les fichiers cachés sous Windows.
cd my_directory && tar -czvf ../my_directory.tar.gz $(ls -A) && cd ..
Celui-ci a fonctionné pour moi et inclut tous les fichiers cachés sans mettre tous les fichiers dans un répertoire racine nommé "." comme dans réponse de tomoe :
Je proposerais la fonction Bash suivante (le premier argument est le chemin du répertoire, le 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 de cette manière:
$ 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. Cela fonctionne avec les éléments cachés (. *) Et avec les éléments avec des espaces dans leur nom de fichier.
Utilisez pax.
Pax est un paquet obsolète, mais fait le travail parfaitement et simplement.
pax -w > mydir.tar mydir
Plus simple j'ai trouvé:
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=-
}
Gère en toute sécurité les noms de fichiers avec des espaces ou d’autres caractères inhabituels. Vous pouvez éventuellement ajouter un filtre -name '*.sql'
ou un filtre similaire à la commande find pour limiter les fichiers inclus.