web-dev-qa-db-fra.com

Comment pouvez-vous décompresser plusieurs fichiers à la fois?

J'ai un tas de fichiers tar dans un répertoire et je veux en extraire tous les fichiers à la fois. Mais cela ne semble rien faire:

$ tar xf *.tar

Que se passe t-il ici? Comment décompresser un tas de fichiers à la fois?

65
Jon Ericson

Que se passe t-il ici?

À l'origine, la commande tar était destinée à être utilisée avec des périphériques de bande magnétique. Puisqu'il était logique d'exécuter tar sur un périphérique à la fois, la syntaxe a été conçue pour supposer un et un seul périphérique. Le premier fichier ou répertoire transmis était supposé être le périphérique qui contenait l'archive en question et tout autre fichier ou répertoire où le contenu de l'archive devait être inclus dans l'opération. Ainsi, pour l'extraction tar (l'option x), le premier fichier transmis serait l'archive et tous les autres fichiers seraient les fichiers à extraire. Donc, s'il y a deux *.tar fichiers (par exemple a.tar et b.tar) votre commande s'étendrait à:

$ tar xf a.tar b.tar

Sauf si a.tar contient un fichier nommé b.tar, la commande tar n'a rien à faire et se ferme silencieusement. De façon ennuyeuse, la version Solaris de tar ne signale aucun problème ni dans le code de retour ni avec l'option détaillée (v). Pendant ce temps, GNU tar résultats 2 et les spams STDERR même avec l'option verbose désactivée:

tar: b.tar: Not found in archive
tar: Exiting with failure status due to previous errors

Comment décompresser un tas de fichiers à la fois?

Il est trop tard de réécrire tar pour accepter plusieurs fichiers d'archive en entrée, mais il n'est pas trop difficile de contourner la limitation.

Pour la plupart des gens, exécuter tar plusieurs fois pour plusieurs archives est l'option la plus appropriée. Passer un seul nom de fichier à tar xf extraira tous les fichiers archivés comme on pourrait s'y attendre. Une approche consiste à utiliser une boucle Shell for:

$ for f in *.tar; do tar xf "$f"; done

Une autre méthode consiste à utiliser xargs:

$ ls *.tar | xargs -i tar xf {}

Alternativement, vous pouvez utiliser l'un d'un certain nombre de lecteurs de fichiers alternatifs tar . Enfin, le programmeur vraiment dédié pourrait facilement écrire un remplacement tar qui fonctionne exactement comme vous le souhaitez. Le format est simple et de nombreux langages de programmation ont des bibliothèques disponibles pour lire les fichiers tar. Si vous êtes un programmeur Perl, par exemple, jetez un œil au Archive::Tar module.

Un avertissement

Détacher aveuglément un tas de fichiers peut provoquer des problèmes inattendus. Le plus évident est qu'un nom de fichier particulier peut être inclus dans plusieurs fichiers tar. Puisque tar écrase les fichiers par défaut, la version exacte du fichier avec lequel vous vous retrouvez dépendra de l'ordre dans lequel les archives sont traitées. Plus troublant, vous pouvez vous retrouver avec une copie corrompue du fichier si vous essayez cette optimisation "intelligente":

for f in *.tar; do
  tar xf "$f" &
done
wait

Si les deux a.tar et b.tar contient le même fichier et essaie de l'extraire en même temps, les résultats sont imprévisibles.

Un problème connexe, en particulier lors de la collecte d'archives à partir d'une source non fiable, est la possibilité d'un tarbomb .

Une solution partielle serait de créer automatiquement un nouveau répertoire dans lequel extraire:

for f in *.tar; do 
  d=`basename "$f" .tar`
  mkdir "$d"
  (cd "$d" && tar xf "../$f")
done

Cela n'aidera pas si un fichier est spécifié dans l'archive avec un chemin absolu (qui est normalement un signe d'intention malveillante). L'ajout de ce type de vérification est laissé comme exercice au lecteur.

129
Jon Ericson

Si tous les fichiers tar sont dans le même dossier, je le fais dans tcsh Shell. Fonctionne tout le temps.

find -iname \*.tar -exec tar -xvf {} \;

C'est la même chose que la réponse ci-dessus, un peu plus concise je pense.

11
Snehashis Roy
find . -maxdepth 1 -name '*.tar' -exec tar -xf '{}' \;
5
user3734617