2012-10-23 14 views
5

Ho un archivio tar che è molto grande ~ 5 GB.Come grep per un pattern nei file nell'archivio tar senza riempire lo spazio su disco

Voglio grep per un modello su tutti i file (e anche stampare il nome del file che ha il modello) nell'archivio ma non voglio riempire il mio spazio su disco estraendo l'archivio.

Ad ogni modo posso farlo?

ho provato questi, ma questo non mi dà i nomi dei file che contengono il modello, solo le linee corrispondenti:

tar -O -xf test.tar.gz | grep 'this' 
tar -xf test.tar.gz --to-command='grep awesome' 

anche dove si trova questa caratteristica di catrame documentati? tar xf test.tar $ FILE

+2

http://stackoverflow.com/questions/2407111/performing-grep-operation-in-tar-files-with-out-extracting –

+0

@OpDeCirkel Dove questa caratteristica di tar è documentata? tar xf test.tar $ FILE – abc

+0

Passato alla sezione degli esempi (ultimo esempio): http://unixhelp.ed.ac.uk/CGI/man-cgi?tar –

risposta

6

Ecco il mio prendere su questo:

while read filename; do tar -xOf file.tar "$filename" | grep 'pattern' | sed "s|^|$filename:|"; done < <(tar -tf file.tar | grep -v '/$') 

rotto fuori per una spiegazione:

  • while read filename; do - si tratta di un ciclo ...
  • tar -xOf file.tar "$filename" - questo estrae ogni file ...
  • | grep 'pattern' - ecco dove si inserisce il modello ...
  • | sed "s|^|$filename:|"; - anteporre il nome del file, quindi questo sembra grep. Sale a piacere
  • done < <(tar -tf file.tar | grep -v '/$') - Termina il ciclo, ottieni l'elenco dei file da battere sul tuo while read.

Una condizione: si interrompe se si hanno barre OR (|) nei nomi file.

Hmm.In realtà, questo fa una bella funzione bash poco, che è possibile aggiungere al vostro .bashrc del file:

targrep() { 

    local taropt="" 

    if [[ ! -f "$2" ]]; then 
    echo "Usage: targrep pattern file ..." 
    fi 

    while [[ -n "$2" ]]; do  

    if [[ ! -f "$2" ]]; then 
     echo "targrep: $2: No such file" >&2 
    fi 

    case "$2" in 
     *.tar.gz) taropt="-z" ;; 
     *) taropt="" ;; 
    esac 

    while read filename; do 
     tar $taropt -xOf "$2" \ 
     | grep "$1" \ 
     | sed "s|^|$filename:|"; 
    done < <(tar $taropt -tf $2 | grep -v '/$') 

    shift 

    done 
} 
+0

Odio grazie su SO, ma questo mi ha davvero aiutato - thx (: – drevicko

3

Ecco una funzione di bash che potrebbe funzionare per te. Aggiungere quanto segue al ~/.bashrc

targrep() { 
    for i in $(tar -tzf "$1"); do 
     results=$(tar -Oxzf "$1" "$i" | grep --label="$i" -H "$2") 
     echo "$results" 
    done 
} 

Usage:

targrep archive.tar.gz "pattern" 
+0

Questo non funziona. Stampa (input standard) come nome del file. Ho provato con -l e -H. – abc

+0

@abc: questa versione funziona meglio per te? – Steve

+1

Doh, non ho visto la tua funzione bash prima di scrivere il mio. E il tuo è più bello del mio. :-) ** + 1 **. (Ora che controllo, sembra che il tar di FreeBSD riconosca automaticamente i file compressi, quindi il mio riconoscimento dei nomi dei file potrebbe essere ridondante.) – ghoti

0

Prova:

tar tvf name_of_file |grep --regex="pattern" 

L'opzione t metterà alla prova il file tar senza estrarre i file. La v è prolissa e la f stampa i nomi dei file. Questo dovrebbe farti risparmiare spazio sul disco rigido.

+0

Anche questo non è corretto. Hai provato questo prima di postare? – abc

+1

Cosa c'è che non va, @abc? Non estrae i file; ottiene i nomi dei file sullo standard output e greps per loro. Che risultato hai ottenuto? Oppure il problema è che vuoi ottenere i nomi dei file che contengono il pattern nel corpo del file senza estrarre i file ... è più difficile, ma non chiaramente descritto nella domanda. –

+0

@JonathanLeffler Ok aggiunto. – abc

1

È incredibilmente hacky, ma è possibile utilizzare l'opzione -v di tar per elaborare ed eliminare ogni file mentre viene estratto.

grep_and_delete() { 
    if [ -n "$1" -a -f "$1" ]; then 
    grep -H 'this' -- "$1" </dev/null 
    rm -f -- "$1" </dev/null 
    fi 
} 
mkdir tmp; cd tmp 
tar -xvzf test.tar.gz | (
    prev='' 
    while read pathname; do 
    grep_and_delete "$prev" 
    prev="$pathname" 
    done 
    grep_and_delete "$prev" 
) 
+0

http://stackoverflow.com/questions/2407111/performing-grep-operation-in-tar-files-with-out-extracting – abc

+0

In questo modo è più veloce perché decomprime solo il file '.tar.gz' una volta. – aecolley

1
tar -tf test.tar.gz | grep -v '/$'| \ 
xargs -n 1 -I _ \ 
sh -c 'tar -xOf test.tar.gz _|grep -q <YOUR SEARCH PATTERN> && echo _' 
+0

Puoi rispondere alla mia domanda nel commento del post originale? – abc

+0

@abc, se è parte della tua domanda, perché non [aggiungilo alla tua domanda] (http://stackoverflow.com/posts/13041068/edit)? – Graham

9

Sembra come nessuno ha postato questa semplice soluzione che processi l'archivio solo una volta:

tar xzf archive.tgz --to-command \ 
    'grep --label="$TAR_FILENAME" -H PATTERN ; true' 

Qui tar passa il nome di ciascun file in una variabile (vedere the docs) e viene utilizzato da grep per stamparlo con ogni corrispondenza. Inoltre, true viene aggiunto in modo che tar non si lamenta di non riuscire a estrarre i file che non corrispondono.

+1

La migliore risposta, funziona perfettamente e come previsto da tar. – Matt

+0

Il '; true' non funziona per me, quelli vengono passati come argomenti a 'grep', che si lamenta di'; 'e' true' non sono file o directory. –

+0

@DanielH Quale shell stai usando? Questo può influenzare il modo in cui il comando viene analizzato ed eseguito. –

Problemi correlati