tar: aggiunge tutti i file e le directory nella directory corrente COMPRESO .svn e così via


91

Provo a tar.gz una directory e utilizzo

tar -czf workspace.tar.gz *

Il tar risultante include le .svndirectory nelle sottodirectory ma NON nella directory corrente (poiché *viene espanso solo ai file 'visibili' prima di essere passato a tar

ho provato a

tar -czf workspace.tar.gz .invece, ma poi ricevo un errore perché "." è cambiato durante la lettura:

tar: ./workspace.tar.gz: file changed as we read it

Esiste un trucco in modo che *abbini tutti i file (inclusi i punti prefissati) in una directory?

(utilizzando bash su Linux SLES-11 (2.6.27.19)


5
Forse questa domanda appartiene al superutente?
Peter Jaric

Risposte:


78

Non creare il file tar nella directory che stai impacchettando:

tar -czf /tmp/workspace.tar.gz .

fa il trucco, tranne che estrarrà i file in tutta la directory corrente quando si decomprime. Meglio fare:

cd ..
tar -czf workspace.tar.gz workspace

oppure, se non conosci il nome della directory in cui ti trovavi:

base=$(basename $PWD)
cd ..
tar -czf $base.tar.gz $base

(Questo presume che tu non abbia seguito i collegamenti simbolici per arrivare dove sei e che la shell non cerchi di indovinarti saltando all'indietro attraverso un collegamento simbolico - bashnon è affidabile a questo riguardo. utilizzare cd -P ..per fare una directory di cambiamento fisico. Stupido che non sia il comportamento predefinito a mio avviso - confuso, almeno, per coloro per i quali cd ..non ha mai avuto alcun significato alternativo.)


Un commento nella discussione dice:

Devo [...] escludere la directory superiore e [...] posizionare il tar nella directory di base.

La prima parte del commento non ha molto senso: se il file tar contiene la directory corrente, non verrà creato quando estrai il file da quell'archivio perché, per definizione, la directory corrente esiste già (tranne in circostanze molto strane ).

La seconda parte del commento può essere trattata in due modi:

  1. O: crea il file da qualche altra parte - /tmpè una possibile posizione - e poi spostalo di nuovo nella posizione originale dopo che è stato completato.
  2. Oppure: se stai usando GNU Tar, usa l' --exclude=workspace.tar.gzopzione. La stringa dopo il =è un modello - l'esempio è il modello più semplice - una corrispondenza esatta. Potrebbe essere necessario specificare --exclude=./workspace.tar.gzse si sta lavorando nella directory corrente contrariamente ai consigli; potrebbe essere necessario specificare --exclude=workspace/workspace.tar.gzse si sta lavorando su un livello come suggerito. Se hai più file tar da escludere, usa " *", come in --exclude=./*.gz.

1
Buona risposta ma ho una situazione in cui sono costretto a eseguire questo comando all'interno della directory che deve essere compressa. Non ho autorizzazioni sufficienti per eseguirlo all'esterno.
Hexodus

Un posto perfetto per fare i bagagli è sicuramente / tmp.
Andre Fellows

46

Se davvero non vuoi includere la directory principale nel tarball (e questa è generalmente una cattiva idea):

tar czf workspace.tar.gz -C /path/to/workspace .

Ho bisogno di escludere la directory principale e ho bisogno di posizionare il tar nella directory di base.
Micha

@Micha crea uno script bash per archiviare e copiare il file dopo
Fedir RYKHTIK

2
Ti manca il - in -czf credo.
UpTheCreek

10
man tar: il primo argomento di tar dovrebbe essere una funzione; una delle lettere Acdrtuxo uno dei nomi lunghi delle funzioni. Una lettera di funzione non ha bisogno di essere preceduta da- e può essere combinata con altre opzioni di una sola lettera.
rkhayrov

4
Ancora non funziona, ho ancora il "." come directory principale nel mio tarball
A. Gille

44

Ci sono un paio di passaggi da eseguire:

  1. Sostituisci *con .per includere anche i file nascosti.
  2. Per creare l'archivio nella stessa directory è --exclude=workspace.tar.gzpossibile utilizzare un per escludere l'archivio stesso.
  3. Per prevenire l' tar: .: file changed as we read iterrore quando l'archivio non è ancora stato creato, assicurati che esista (es. Usando touch), in modo che --exclude corrisponda al nome del file dell'archivio. (Non corrisponde al file non esiste)

Combinato questo risultato nel seguente script:

touch workspace.tar.gz
tar -czf workspace.tar.gz --exclude=workspace.tar.gz .

7
Ho letto tutte le risposte e i commenti e questo è il modo migliore per creare tarball nella stessa directory. Da questa risposta ho anche capito perché si verifica questo errore.
Szymon Sadło

Se volete vedere i progressi mentre è comprimere il file tar, è possibile aggiungere una bandiera addizionale per --verbose, in questo modo: -czvf.
Mastrianni

19

nella directory vuoi comprimere (directory corrente) prova questo:

tar -czf workspace.tar.gz . --exclude=./*.gz

2
Ma ora si lamenta che il file "." cambiato durante la lettura. Posso essere sicuro che tutti i file siano stati inclusi?
Jaan

1
Ciò esclude tutti i .gzfile nella directory.
omerfarukdogan

12

Puoi includere le directory nascoste tornando indietro in una directory e facendo:

cd ..
tar czf workspace.tar.gz workspace

Supponendo che la directory che si desidera gzip fosse chiamata area di lavoro.


E questo evita anche il problema della modifica del file.
Jonathan Leffler

Non funziona quando l'utente non dispone dell'autorizzazione di scrittura nella cartella principale.
Joachim Wagner

Esattamente @JoachimWagner!
p01ymath

1
@JoachimWagner. Se non hai il permesso di scrittura, tar -czf /path/to/where/you/do/have/permission/workspace.tar.gz workspace
cambialo in

1
Ho dovuto toglierlo -prima czfdi farlo funzionare. Altrimenti stavo ricevendo Cannot stat: No such file or directoryun messaggio di errore.
Phemelo Khetho,

6

Puoi correggere il .modulo utilizzando --exclude:

tar -czf workspace.tar.gz --exclude=workspace.tar.gz .

5

Aggiornamento: ho aggiunto una correzione per il commento dell'OP.

tar -czf workspace.tar.gz .

cambierà effettivamente la directory corrente, ma perché non posizionare il file da qualche altra parte?

tar -czf somewhereelse/workspace.tar.gz .
mv somewhereelse/workspace.tar.gz . # Update

Il file verrà elaborato in seguito e deve essere nell'area di lavoro - è un po 'brutto ma è solo necessario (il tutto è solo una soluzione alternativa ...)
Micha

OK, aggiungerò una correzione per questo :)
Peter Jaric

E se hai bisogno di essere in grado di eseguirlo ripetutamente, aggiungi 'rm workspace.tar.gz' prima della riga tar.
Peter Jaric

Se vuoi tarare un intero disco, nella stessa unità, sembra che tu non abbia molte opzioni.
BeeOnRope

4

In realtà il problema è con le opzioni di compressione. Il trucco sta nel convogliare il risultato di tar a un compressore invece di usare le opzioni integrate. Per inciso, questo può anche darti una compressione migliore, poiché puoi impostare opzioni di compressione extra.

Tar minimo:

tar --exclude=*.tar* -cf workspace.tar .

Collega un compressore a tua scelta. Questo esempio è dettagliato e utilizza xz con la massima compressione:

tar --exclude=*.tar* -cv . | xz -9v >workspace.tar.xz

La soluzione è stata testata su Ubuntu 14.04 e Cygwin su Windows 7. È una risposta wiki della comunità, quindi sentiti libero di modificare se noti un errore.


Grazie! Ha salvato la vita
Steven

2

Il problema con la maggior parte delle soluzioni fornite qui è che tar contiene ./alla richiesta di ogni voce. Quindi questo si traduce in una .directory quando viene aperta tramite il compressore della GUI. Quindi quello che ho finito per fare è:

ls -1A | xargs -d "\n" tar cfz my.tar.gz

Se hai già my.tar.gznella directory corrente, potresti volerlo estrarre:

ls -1A | grep -v my.tar.gz | xargs -d "\n" tar cfz my.tar.gz

Tieni presente che xargs ha un certo limite (vedi xargs --show-limits). Quindi questa soluzione non funzionerebbe se stai cercando di creare un pacchetto che ha molte voci (directory e file) su una directory che stai cercando di tarare.


1

Una bella domanda. In ZSH puoi usare il modificatore globbing (D), che sta per "dotfiles". Confrontare:

ls $HOME/*

e

ls $HOME/*(D)

Ciò esclude correttamente le voci di directory speciali .e ... In Bash puoi usare .*per includere esplicitamente i dotfile:

ls $HOME/* $HOME/.*

Ma questo include anche .e .., quindi non è quello che stavi cercando. Sono sicuro che ci sia un modo per far *corrispondere i dotfile anche in bash.


In bash, usa .??*per abbinare tutti i file punto non .e ... Questo non ottiene file di punti a carattere singolo (come .a). Per ottenere anche quelli, usa il più complicato .[^.]*.
Scott Minster

1

Ancora un'altra soluzione, supponendo che il numero di elementi nella cartella non sia enorme:

tar -czf workspace.tar.gz `ls -A`

( ls -Astampa file normali e nascosti ma non "." e ".." come ls -afanno.)


0
tar -czf workspace.tar.gz .??* *

La specifica .??*includerà file "punto" e directory che hanno almeno 2 caratteri dopo il punto. Il lato negativo è che non includerà file / directory con un singolo carattere dopo il punto, ad esempio .a, se ce ne sono.


0

Se lo spazio su disco non è un problema, questa potrebbe anche essere una cosa molto semplice da fare:

mkdir backup
cp -r ./* backup
tar -zcvf backup.tar.gz ./backup

0

Ho avuto una situazione simile anch'io. Penso che sia meglio creare il tar altrove e quindi utilizzare -C per indicare a tar la directory di base per i file compressi. Esempio:

tar -cjf workspace.tar.gz -C <path_to_workspace> $(ls -A <path_to_workspace>)

In questo modo non è necessario escludere il proprio file tar. Come notato in altri commenti, -A elencherà i file nascosti.


0

10 anni dopo, hai un'alternativa a tar, illustrata con Git 2.30 (Q1 2021), che usa " git archive" ( man ) per produrre il tarball di rilascio invece di tar.
(Non è necessario Git 2.30 per applicare tale alternativa)

Vedere commit 4813277 (11 ottobre 2020) e commit 93e7031 (10 ottobre 2020) di René Scharfe ( rscharfe) .
(Fuso da Junio ​​C Hamano - gitster- in commit 63e5273 , 27 ottobre 2020)

Makefile: usa git init / add / commit / archive per dist-doc

Firmato da: René Scharfe

Riduci la dipendenza da strumenti esterni generando gli archivi di distribuzione per la documentazione HTML e le pagine man usando i comandi ( man ) invece di tar. Ciò fornisce alle voci dell'archivio gli stessi metadati di quelli nell'archivio dist per i binari.git

Quindi invece di:

tar cf ../archive.tar .

Puoi farlo usando solo Git:

git -C workspace init
git -C workspace add .
git -C workspace commit -m workspace
git -C workspace archive --format=tar --prefix=./ HEAD^{tree} > workspace.tar
rm -Rf workspace/.git

Questo è stato inizialmente proposto perché, come spiegato qui , alcune piattaforme esotiche potrebbero avere una vecchia distribuzione tar con opzioni mancanti.


-1

L'utilizzo findè probabilmente il modo più semplice:

find . -maxdepth 1 -exec tar zcvf workspace.tar.gz {} \+

find . -maxdepth 1troverà tutti i file / directory / collegamenti simbolici / ecc nella directory corrente ed eseguirà il comando specificato da -exec. Nel {}comando significa che l'elenco dei file va qui e \+significa che il comando verrà eseguito come:

tar zcvf workspace.tar.gz .file1 .file2 .dir3

invece di

tar zcvf workspace.tar.gz .file1
tar zcvf workspace.tar.gz .file2
tar zcvf workspace.tar.gz .dir3

-J è --xz nel manuale; combinato con -c è solo l'inizio di ciò che un computer chiamerà "divertimento" :)
Ricalsin

Haha, il mio mini-server a casa è più limitato dallo spazio su disco che dalla CPU :) Buona osservazione però; Lo cambierò per usare gzip.
Andrew Gunnerson
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.