[Hdparm] [Hdparm] [About] [Copertina] [Kernel korner] [Kernel korner]

Articoli


Comandi Unix buffi: tar

di Maurizio Codogno

Ristampato con il permesso della rivista
BETA

Caro lettore,
ti eri accorto che avevo dimenticato una delle opzioni di sort, nell'articolo del numero scorso? No? Male. O magari bene: non he hai mai avuto bisogno, e ciò è bello, perché significa che non è che poi hai tantissimo da ordinare, o che hai tanto spazio.
L'opzione saltata per un refuso[1] è infatti

-T tmpdir

e serve a specificare un'altra directory dove fare a scrivere i file temporanei di cui sort ha bisogno. In genere, infatti, viene usata /tmp, ma a volte può essere necessario spostarsi in caccia di posto libero. Tra l'altro, il GNU sort deve essere stato scritto da qualcuno abituato a lavorare sotto DOS: se infatti esso trova settata la variabile di ambiente TMPDIR, usa quel valore come directory di lavoro.

Questa volta tocca a tar. Il nome sta per "tape archiver", cioè archiviatore su nastro: ma oramai sei abbastanza smaliziato per sapere che le probabilità di usare il comando su un vero nastro sono ben poche. Intendiamoci: se il tuo sysadm ha configurato le cose per bene e tu hai un'unità nastro, puoi archiviarci i tuoi file scrivendo semplicemente tar c . (il punto è parte del comando, non finisce la frase!). Ma visto che tanto la risposta sarà più o meno

tar: can't open /dev/rmt0 : Permission denied

o qualcosa di simile, ti conviene lasciare perdere e metterti a leggere i veri usi del comando. Una nota: se non hanno migliorato la man page nelle ultime versioni, il GNU tar è proprio incomprensibile. Peccato.

Funzioni fondamentali

Il comando mostrato sopra fa comunque già notare la prima peculiarità: non si usa il - davanti alle opzioni. Questo non è totalmente vero: in un impeto di bontà, nelle versioni attuali di tar è comunque possibile far precedere le opzioni dal carattere '-' senza che il sistema si preoccupi. In genere, comunque, la sintassi del comando è questa:

   tar {un gruppone di lettere} {un po' di parametri relativi
       alle lettere stesse} [ -I file_include ] file(s) 
       [ -C directory file]
il che dice poco o nulla. Specificando qualcosa in più, scopriamo che alcune lettere del "gruppone" rappresentano le funzioni fondamentali del comando, e ce ne può essere una e una sola, che si mette in genere come primo carattere tanto per ricordarsi cosa si sta facendo. Le altre lettere possono essere presenti o no; se lo sono, e inoltre hanno dei parametri, questi sono indicati nello stesso ordine in cui la lettera corrispondente si trova nel gruppone. Non ci sono quindi problemi di parsificazione per il sistema; magari ne rimane qualcuno per il povero utente, che deve spostarsi avanti e indietro tra il gruppone e i parametri per capire chi si riferisce a cosa.

Il file non è un semplice nome, o per meglio dire una semplice espressione regolare come ad esempio "*": se infatti corrisponde a una directory, viene lanciata la ricorsione e quindi tar comincia a infilarsi nei meandri del file system riportando alla luce reperti imprevisti. La ricorsione è fatta per bene, e comprende anche i file i cui nomi iniziano con un punto e pertanto sono nascosti; insomma, se si vuole salvare tutto un sottoalbero basta partire da ".".

Le funzioni principali sono cinque: c, r, t, u, x.

  • c sta per crea: viene costruito un archivio con i file che si indicheranno nel resto del comando.
  • r sta per rimpiazza: i file che si indicheranno verranno aggiunti al fondo dell'archivio, che ovviamente deve esistere già. E se ce n'erano già con quel nome, ti chiederai? Nic problema! Per come funziona il comando, quando sono presenti più file con lo stesso nome ognuno viene scritto sul precedente, e quindi rimarrà solo l'ultimo.
  • t sta per testa[2]: serve per vedere quali file sono presenti in un archivio.
  • u sta per update (aggiorna): è simile alla funzione r, ma se i file erano già presenti e non sono stati modificati si evita di sprecare spazio.
  • x sta per estrai: è la funzione che si usa per tirare fuori questi benedetti file dall'archivio! In realtà spesso non si dice nemmeno quali sono i file (anche per i problemi con path relativi e assoluti), e in questo caso si suppone che si vuole estrarre tutto.

il GNU tar, per non smentirsi, ne ha aggiunte altre due, che non sono comunque così necessarie almeno a mio parere:

  • A, che appende un altro file tar (e non un singolo file) all'archivio;
  • d, che verifica se ci sono differenze tra i file di un archivio e quelli che si trovano nella directory, in modo da sapere cosa è cambiato.

Ah, dimenticavo: il GNU tar permette sempre di scrivere per esteso i nomi delle funzioni, facendoli precedere da -- (due segni meno). Serve? non serve? per me è solo una perdita di tempo.

Funzioni modificanti

Nel cosiddetto gruppone, ci sono davvero tante lettere. Parlerò qui solo delle principali, vista la mia solita pigrizia. Tanto non capita praticamente mai di usarle tutte! Come ho detto sopra, se la funzione ha un parametro, questo lo si trova bello ordinato dopo il gruppone stesso.

  • b nn indica quanti gruppi da 512 byte bisogna scrivere in un colpo solo (un blocco). Si usa solo quando si scrive su nastro, e in genere si lascia a 20 perché ottimizza la velocità di scrittura.
  • B costringe tar ad aspettare che sia completamente terminato il blocco di cui sopra, prima di scrivere. Se si usa tar come filtro, e lo si manda attraverso la rete, è facile che ci siano dei timeout e il sistema creda che i dati siano finiti: e ciò non è bello.l
  • f filename serve per dare il nome del file (vero o device che sia) da usare come archivio. Se non lo si scrive, tar comincia a controllare se la variabile di ambiente TAPE è settata a qualcosa. Sennò. si prende il valore di default, tipicamente /dev/rmt0[3]. Se lo si scrive, si usa quello: caso speciale è il nome -, che sta per standard input o standard output a seconda di cosa sia più logico. In questo modo, il comando si trasforma automagicamente in un filtro, e i veri amanti di Unix si sentono immediatamente a casa.
  • h serve per dire a tar di leggere i file, o le directory, puntate dai link simbolici. In genere, infatti, viene semplicemente salvato il nome del link.
  • p permette di salvare, oppure di estrarre, informazioni supplementari sui permessi del file, come ad esempio il bit setuid. Tutto questo ovviamente se si è root: pensa altrimenti come sarebbe divertente creare programmi troiani!
  • v è la funzione "verbose", che dice tutto quello che vogliamo sapere quando creiamo un archivio o ne estraiamo dei file. Dopo un po', rimane una cosa talmente automatica che bisogna farsi forza per non aggiungerla quando non solo non è necessaria, ma anzi dà fastidio. Pensa che bello usare due tar uno accodato all'altro, come farò negli esempi, e vedere a video l'output di uno e dell'altro belli mischiati...
  • w serve per darci la possibilità di essere decisionisti. In pratica, tutte le volte che dovrebbe fare qualcosa, tar ci chiede conferma: se rispondiamo con una parola che inizia con y (minuscola), esegue l'azione, altrimenti lascia perdere.
  • X exclude-file indica il nome di un file dove si possono scrivere, uno per riga, tutti i file che non si vuole considerare con le funzioni c,t e x. Si possono avere più funzioni X, ciascuna corrispondente a un file. Due noticine: ricordati che quando salvi i file in un archivio, spesso i loro nomi cominciano con ./ ; e ricordati di inserire il nome stesso del file di esclusione al suo interno!

Tanto per darti un'idea, ho lasciato da parte le seguenti funzioni per il tar Solaris: e,F,FF,i,l,m,o. Il GNU tar ha invece le seguenti funzioni denominate con una lettera: F,G,g,i,k,K,L,m,o,O,R,s,S,T,V,W, oltre che un'altra dozzina per cui non si erano trovate lettere dell'alfabeto disponibili[4]. Non è detto che le opzioni corrispondano: F,i, ed o sono infatti cose diverse. Esistono anche funzioni definite da una cifra tra 0 e 7, che serve a specificare un device file differente.

Alcune funzioni GNU sono però simpatiche, e vale la pena di darci un'occhiata.

  • l serve a dire di non cambiare file system, anche se la foga della ricorsione nella creazione di un archivio lo richiederebbe. La cosa non è peregrina come sembra: lo si vedrà negli esempi. Non è inutile fare notare che il tar Solaris ha una concezione completamente diversa di l; serve infatti ad arrabbiarsi se non esiste il file a cui un link simbolico punta.
  • M permette di creare un archivio in più parti, da usare se si vuole spezzare un file in più floppini.
  • P lascia la barra iniziale / nei nomi dei file che vengono salvati. Non è una bella cosa (infatti il GNU tar tipicamente la toglie), ma qualcuno può trovarla comoda.
  • z (e la sorellina Z) è però l'unica funzione per cui vale davvero la pena di installare il GNU tar se non lo si ha. Con questa infatti si può usare gzip (o rispettivamente compress) per comprimere e decomprimere gli archivi. Chi arriva dal mondo dos si è sempre chiesto perché sotto Unix ci sono due comandi distinti per archiviare e comprimere, e non un unico zip. Bene, a parte il fatto che così ce n'è uno solo[5], la vera ragione è che si comprime meglio un unico file che tanti pezzetti, anche se al prezzo di perdere tutto se il primo file risulta corrotto.

Funzioni separate

Le due funzioni che se ne stanno da sole sono, come visto sopra, -I include_file e -C directory file. La prima funziona più o meno come X: si apre il file e si legge la lista di file su cui occorre operare. Attento a non usare spazi, che verrebbero considerati parte del file, e ricordati che se un file è contemporaneamente incluso ed escluso, quest'ultima condizione prevale.

La funzione -C è un po' più delicata. Viene usata solo con le funzioni c ed r, e richiede esattamente due parametri: il programma usa il primo come argomento di una chdir, e quindi si posiziona altrove, e il secondo indica quale file (ricorsivamente) salvare. In pratica, si ha la possibilità di salvare file sotto directory scorrelate senza dovere partire dalla radice e selezionare solo le parti che interessano. Meglio che niente anche in questo caso.

Esempi

Un paio di esempi non fanno certo male. Cominciamo con la cosa più usuale: estrarre un pacchetto in formato .tar.gz. Il comando da darsi sotto GNU tar (magari dopo avere controllato con

tar tvzf pippo.tar.gz | head

se occorre lasciare il file in una directory propria oppure se la crea lui) è

   % tar xvzf pippo.tar.gz
con la v facoltativa. Non si ha il GNU tar? nessun problema: la soluzione è allora
   % zcat pippo.tar.gz | tar xvf -
in cui si vede anche con piacere il fatto che lo pseudofile - in questo caso indica lo standard input.

Se si vuole creare un file tar con la directory pippo e tutti i file sottostanti, la risposta è data da

   % tar cvf pippo.tar pippo
(meglio che posizionarsi in pippo e scrivere tar cvf ../pippo.tar . - almeno a mio parere.

Se si vuole copiare un sottoalbero da un'altra parte in un solo colpo, non si può usare cp, come ormai sanno anche i bambini; tar è proprio quello che ci vuole, usato due volte in una pipe.

   % cd fromdir; tar cf - | (cd todir; tar xf -)
Avendo una pipe, dobbiamo chiaramente usare lo pseudofile - in entrambi i casi; ci serve inoltre racchiudere il secondo comando in una sottoshell, perché dobbiamo essere certi che il file sia salvato nella directory corretta. Altrimenti, la pipe terminerebbe con il cd, si perderebbe tutto l'input e il secondo tar non saprebbe da dove prendere i dati.

Infine, un comando d'alta scuola: un tar in rete. Supponiamo di avere un nastro su un'unità remota e di volerlo utilizzare. Purtroppo non abbiamo la possibilità di copiare tutti i nostri file sul calcolatore remoto, e comunque siamo talmente innamorati delle pipe che vogliamo sfruttarle ad ogni pié sospinto. Bene: se sei stato attento, saprai che b e B dovranno servirci perché abbiamo un nastro e lavoriamo in rete, e rsh non è certo dimenticato. Tutto qui? No. Ovviamente non si può usare tar da ambo le parti. Ci si incasinerebbe con le dimensioni dei blocchi. Ma niente paura, c'è il nostro vecchio amicone dd! Ecco in primo luogo come si salva il sottoalbero che parte da pippo su un nastro remoto sulla macchina server1:

   % tar cvfb - 20 pippo | rsh server1 dd of=/dev/rmt/0 obs=20b
Occorre che la dimesione del blocco per i due comandi sia la stessa. Oltre 20 non si può andare: accontentiamoci. L'operazione inversa è leggermente diversa:
   % rsh -n server1 dd if=/dev/rmt0 bs=20b | tar xvbBf 20 - 
In questo caso occorre da un lato dare entrambe le dimensioni dei blocchi a dd, dall'altra ricordarsi che il tar in ingresso riceverà dati a spizzichi e bocconi, e che occorrerà pertanto tranquillizzarlo un po' con la funzione B. Ma non preoccuparti più di tanto se te la dimentichi: un tar decente si accorge di essere in una pipe e te la potrebbe aggiungere di tuo!

Una parolina finale

La miniserie dedicata ai "comandi buffi Unix" è così terminata: ti sei cuccato find, dd, sort e tar, che in realtà sono i comandi più usati che hanno un'interfaccia relativamente strana. Non sono gli unici, a dire il vero: a me viene ad esempio in mente cpio che è abbastanza simile a tar per non valer la pena di studiarlo, e dump che oggi è relativamente poco usato, perché nascosto all'interno dei programmi di backup. In pratica si può comunque affermare che la sintassi di tutti gli altri comandi è sempre la stessa. Pensaci un attimo: non ti rincuora sapere di potere contare su un po' di sana monotonia?

Il problema è adesso mio. Infatti, devo decidere cosa scrivere nei prossimi numeri. Non ci crederai, ma alle volte è più difficile stabilire cosa scrivere che mettermi poi davvero a scriverlo. Idee? Beh, potrei continuare a trattare i comandi Unix (ls, o grep, o persino bc, ad esempio); oppure sviscerare qualche segreto sui programmi di utilità che si trovano spesso inseriti proditoriamente negli shell script e che si danno per scontate, come awk e sed; o ancora scrivere di vi, l'editor del Vero Programmatore quando non è di fretta[6]. Siccome so che tu sei intelligente, immagino che hai già sentito puzza di feedback. Perché non mi mandi una letterina con le tue preferenze? Possibilmente prima di Natale, anche se non ti regalerò nulla...

Note & Chiose

[1]
Dicono sempre così...
[2]
In realtà sarebbe il TOC, o Table of Contents: ma in pratica lo si usa per vedere se va tutto bene!
[3]
Che è un'unità a nastro formato pizza. Reperto da museo, insomma. Ma questo è nulla rispetto a cat, anzi C/A/T ...
[4]
Che siano stati gli amici GNU a fare lobbying per Unicode, in modo da avere decine di migliaia di caratteri disponibili?
[5]
Barando, però: infatti occorre che il comando di (de)compressione sia presente nel path.
[6]
Il Vero Programmatore quando ha fretta usa ed, che non lo infastidisce con prolissi messaggi di errore, e quando ha veramente fretta scrive direttamente con cat>nomefile quello che gli serve.

Maurizio Codogno è reperibile su Internet tramite la redazione di BETA


[Hdparm] [Hdparm] [About] [Copertina] [Kernel korner] [Kernel korner]