2013-10-06 12 views
10

quindi lasciatemi spiegare questo un po 'di più:Bash. Ottenere intersezione da più file

Ho una directory chiamata tag che ha un file per ogni tag, qualcosa come:

tags/ 
    t1 
    t2 
    t3 

In ciascuno dei file tag è una struttura come:

<inode> <filename> <filepath> 

Naturalmente, ogni file di tag avrà un elenco di molti file con quel tag (ma un file può apparire solo nel file un tag una volta). E un file potrebbe trovarsi in più file di tag.

Quello che voglio essere in grado di fare è chiamare un comando come

tags <t1> <t2> 

e lo hanno elencare i file che hanno sia il t1 e t2 tag in un bel modo.

Il mio piano adesso era di creare un file temporaneo. In pratica, genera l'intero file di t1 in esso. Quindi esegui ogni riga in t2 e fai un awk sul file. E continua a farlo.

Ma mi chiedo se qualcuno ha altri modi. Io non sono eccessivamente familiarità con awk, grep ecc

+0

La stessa riga può apparire più volte in un singolo file? –

+0

No. Il modo in cui l'ho adesso è che il file sarà nel file dei tag solo una volta. – Jonovono

+0

BashFAQ # 36 è on-point: http://mywiki.wooledge.org/BashFAQ/036 –

risposta

13

Potete utilizzare

sort t1 t2 | uniq -d 

Ciò combinare i due file, ordinarli, e quindi visualizzare solo le righe che compaiono più di una volta: cioè, quelli che appaiono in entrambi i file.

Questo presuppone che ciascun file contiene duplicati all'interno di esso, e che gli inode sono uguali in tutte le strutture per un particolare file.

+0

Questo è fantastico. Molto più facile, grazie!Tuttavia, ciò non riesce se si sta tentando di elencare da un solo file di tag: sort t1 | uniq -d. (Qualunque soluzione?) – Jonovono

+1

Um ... 'cat t1'? :-) –

+1

hah. Ya, lo avrei modificato subito dopo che avevo chiesto di essere come il duhhh. Grazie mille :) – Jonovono

15

Si potrebbe provare con comm utilità

comm -12 <t1> <t2> 

comm con un'appropriata combinazione di optionns followinng può essere utile per le diverse operazioni di set sul contenuto dei file.

-1  suppress column 1 (lines unique to FILE1) 

    -2  suppress column 2 (lines unique to FILE2) 

    -3  suppress column 3 (lines that appear in both files) 

Questo presuppone <t1> e <t2> sono ordinati. In caso contrario, dovrebbero essere prima ordinati con sort

+1

TIL 'comm' dopo aver usato linux per oltre un decennio. Grazie! –

+2

@AdamLiss Prego. Ho imparato l'opzione '-d' di' uniq' dalla tua soluzione. Grazie in cambio. Credito per la condivisione delle conoscenze SO. Saluti! – jkshah

+1

Molto più efficiente della risposta accettata. –

0

Versione per più file:

eval `perl -le 'print "cat ",join(" | grep -xF -f- ", @ARGV)' t*` 

espande in:

cat t1 | grep -xF -f- t2 | grep -xF -f- t3 

file di prova:

seq 0 20 | tee t1; seq 0 2 20 | tee t2; seq 0 3 20 | tee t3 

uscita:

0 
6 
12 
18 
+0

Questo è pericoloso - cosa succede se si ha un file chiamato 't $ (rm -rf.)'? –