21:03 <@valhalla> Ciao a tutti, benvenuto alla quinta lezione del corso sulla riga di comando 21:03 <@valhalla> come al solito, spostarsi sulla directory delle altre volte con cd, pwd ed ls per controllare, e poi si pu`o scaricare il materiale di stasera 21:03 <@valhalla> wget http://www.lifolab.org/corsi/2014-linea_di_comando/riga_di_comando-lezione_5.tar.xz 21:03 <@valhalla> e poi scompattarlo con tar -x -v -f riga_di_comando-lezione_5.tar.xz 21:05 <@valhalla> come al solito, se ci sono domande si possono fare sul canale #lifo-comande 21:05 <@valhalla> ehm 21:05 <@valhalla> #lifo-domande 21:06 <@valhalla> dove c'è diego71 che le riporta qui in canale (o se avete qualche problema vi aiuta direttamente a risolverlo) 21:07 <@valhalla> l'argomento di stasera è "cercare le cose" 21:09 <@valhalla> negli ultimi anni si sono diffuse un sacco di soluzioni (specialmente da interfaccia grafica) per indicizzare i file e poi ritrovarli, ma stasera parliamo dei due tool base forniti dall'interfaccia testuale per cercare file (find) e per cercare nei contenuti dei file 21:09 <@valhalla> innanzitutto, prepariamo l'ambiente: ``cd lezione_5`` ``mkdir esercizi`` ``cd esercizi`` 21:09 <@valhalla> a questo punto, possiamo ricordare che già nella prima lezione avevamo parlato di caratteri speciali per indicare pi`u file con una stringa sola 21:10 <@valhalla> ad esempio, ``ls ../../lezione_?`` vi elenca i contenuti di tutte le directory col nome che inizia per ../../lezione_ seguito da un solo carattere 21:11 <@valhalla> questo è parte del cosiddetto "globbing", ovvero una sintassi abbastanza semplice per specificare più stringhe in base ad un pattern che queste rispettano 21:12 <@valhalla> l'altro carattere molto usato che avevamo visto è ``*``, che indica zero o pi`u caratteri qualsiasi 21:12 <@valhalla> (qui c'è un errore nelle dispense, dove ho scritto uno o più, invece vale anche zero caratteri) 21:13 <@valhalla> ad esempio, prepariamoci un po' di file con ``touch file_uno file_due file_tre file_quattro cinque``, che crea un po' di file vuoti 21:13 <@valhalla> ``ls`` per vedere cosa c'è, e poi ``ls file_*`` che vedremo stamperà solo ``file_uno file_due file_tre file_quattro``, ma non ``cinque`` 21:14 <@valhalla> possiamo anche vedere tutti i file con un numero da tre caratteri, con ``ls file_???`` 21:14 <@valhalla> (quindi né file_quattro, né cinque) 21:16 <@valhalla> questo globbing viene effettuato direttamente dalla shell, che poi passa ai programmi l'elenco dei file che soddisfacevano i requisiti 21:16 <@valhalla> ci sono domande fin qui? 21:17 <@valhalla> ovviamente, elencare file in questo modo non è molto utile ai fini del trovare qualcosa che non sappiamo dove sia :) 21:17 <@valhalla> a questo viene in aiuto il comando find 21:19 <@valhalla> find è un comando che ha una sintassi leggermente diversa dal solito, e a volte fa uso di magia nera, ma serve per trovare sul filesystem dei file che soddisfano determinate condizioni nei *metadata* 21:20 <@valhalla> ovvero, può fare ricerche sul nome, sul tipo di file, sulla data, proprietario, dimensioni e quant'altro, ma non sui contenuti 21:20 <@valhalla> la sintassi è ``find $DOVE_CERCARE $COSA_CERCARE`` 21:21 <@valhalla> dove $COSA_CERCARE è composto da varie opzioni -nome_opzione valore 21:21 <@valhalla> ad esempio, diamo il comando ``touch file_une`` 21:22 <@valhalla> e poi ``find ../../ -name "file_un?" 21:22 <@valhalla> notare le ": servono perché vogliamo che sia find a leggere quel ?, non vogliamo che venga interpretato dalla bash 21:23 <@valhalla> se non avessimo messo le virgolette, ``find ../../ -name file_un?`` sarebbe stato trasformato in ``find ../../ -name file_une file_uno``, che non è quello che vogliamo (e da errore) 21:23 <@valhalla> quel comando trova nella directory ../../ tutti i file il cui nome è ``file_un`` seguito da un carattere qualsiasi, e niente altro 21:24 <@valhalla> se usiamo ad esempio ``find ../../ -name "file_u?"`` non troverà niente, mentre nel nostro caso specifico ``find ../../ -name "file_u??" troverà gli stessi file 21:24 <@valhalla> domande fin qui? 21:24 <@valhalla> direi di no, proseguo 21:25 <@valhalla> un altra condizione che ogni tanto si usa sono le dimensioni, ad esempio ``find ../../ -size 1504c`` trova tutti i file che occupano esattamente 1504 byte 21:26 <@valhalla> il suffisso ``c`` sta per byte, ci sono anche k, M e G che stanno più intuitivamente per kilobyte, megabyte e gigabyte 21:27 <@valhalla> (può essere utile ad esempio per trovare file da esattamente 2G, che probabilmente son stati troncati su qualche filesystem primitivo :) 21:28 <@valhalla> per il nome, dimenticavo, c'è anche la variante -iname, che cerca il nome ignorando maiuscole e minuscole 21:28 <@valhalla> e poi ci sono millemila altre opzioni, che si trovano sulla pagina di manuale 21:29 <@valhalla> domande fin qui? 21:29 <@diego71> < tiziano> perché find ../../ e non find . (directory corrente)? 21:29 <@valhalla> perché così trovava anche riga_di_comando-lezione_5.tar.xz che è quello di cui avevo controllato le dimensioni :) 21:30 <@valhalla> effettivamente più spesso lo si fa o sulla directory corrente oppure su qualche directory "famosa" 21:30 <@valhalla> tipo ``find /home -size +128M`` per trovare che utenti di un sistema stanno sprecando spazio :D 21:31 <@valhalla> altre domande? 21:31 <@valhalla> (ovvero, trovare i file nelle directory sotto ``/home`` che occupano più di 128 MB 21:32 <@diego71> riassumo la domanda di gioque: differenze tra find e locate 21:33 <@valhalla> locate tiene un indice di tutti i nomi di file che c'erano sul filesystem quando ha fatto ha fatto la passata di indicizzazione 21:34 <@valhalla> di solito i sistemi sono configurati (tramite cron, che per`o qui è un po' OT) per fare quella passata ogni giorno o ogni settimana, ma se si è aggiunto qualcosa di più recente non lo trova 21:35 <@valhalla> find invece legge i contenuti del disco nel momento in cui lo si lancia, e quindi è in generale pi`u lento, ma permette anche di trovare file recenti e di usare criteri diversi dal nome del file 21:35 <@valhalla> altre domande? 21:36 <@valhalla> < polva> non c'è quindi un modo per trovare file con un range di dimensione? 21:36 <@valhalla> usando due volte -size, una volta con +$DIMENSIONE_MINIMA ed una volta con -$DIMENSIONE_MASSIMA 21:37 <@valhalla> altre domande? 21:37 <@diego71> < tiziano> posso usera find per cercare solo directories rispondenti a determinati criteri? 21:38 <@valhalla> uno dei criteri può essere -type d per dire che quello che vuoi trovare deve essere una directory 21:38 <@valhalla> (oppure -type f per un file regolare, o -type l per un link simbolico) 21:38 <@valhalla> poi dipende da cosa vuoi come "determinati criteri" 21:38 <@valhalla> altre domande? 21:39 <@valhalla> un'altra cosa che find può fare è agire sui file trovati 21:39 <@valhalla> non vi faccio esempi dell'opzione -delete, con la quale è mooooolto facile fare danni 21:40 <@valhalla> ma si pu`o eseguire un comando su ciascuno dei file trovati usando l'opzione ``-exec``: 21:40 <@valhalla> ``find ../../ -size 1504 -exec /bin/ls -l {} \; 21:40 <@valhalla> dove dopo exec tutto viene interpretato come il comando da eseguire fino a che non si arriva a \; 21:41 <@valhalla> e al posto di {} andrà il nome del file che è stato trovato 21:41 <@valhalla> in questo caso ho usato un comando che non fa danni, ovviamente il rischio di distruggere dati c'è anche qui, se si usa il comando sbagliato 21:41 <@valhalla> domande? 21:42 <@diego71> < aldagaau> find /home/ -size +128M -150M (da un errore find: Argomento "$" non valido per -size 21:42 <@valhalla> ``find ../../ -size -100c -size +10c`` 21:42 <@valhalla> ci vuole due volte l'opzione -size 21:44 <@valhalla> (nel comando di prima, ho dimenticato c per la dimensione in byte, come era prima non trovava nessun file) 21:44 <@valhalla> (quello giusto è ``find ../../ -size 1504c -exec /bin/ls -l {} \;`` 21:45 <@diego71> < tiziano> $ find /home -type d -size +128M #cosa c'è di sbagliato in questo comando? 21:45 <@valhalla> che le directory hanno sempre come dimensione 4096 byte o qualche valore simile (dipende dal filesystem) 21:45 <@valhalla> i *contenuti* della directory hanno una dimensione ben diversa, ma non è quello su cui find lavor 21:45 <@valhalla> a 21:46 <@valhalla> altre domande? 21:46 <@valhalla> leggo che ci sono problemi con la sintassi di find: se vi state chiedendo se è magia nera, s`i, lo è :) 21:47 <@valhalla> è ancora pi`u pignolo della media dei programmi da riga di comando, ed ha una fraccata di opzioni anche esoteriche 21:47 <@valhalla> se non ci sono altre domande, proseguo 21:48 <@valhalla> con find si cerca tra i metadata dei file, per cercare invece sui contenuti dei file di testo esiste grep 21:48 <@valhalla> grep ha una sintassi che è il contrario di quella di find: ``grep $COSA_CERCARE $FILE_IN_CUI_CERCARE`` 21:49 <@valhalla> e $COSA_CERCARE non è un semplice globbing, ma un espressione regolare 21:49 <@valhalla> che è potenzialmente pi`u potente e più complicata 21:49 <@valhalla> un caso semplice che si usa spesso è selezionare tutte le righe di uno o più file che contengano qualche stringa ben specifica 21:50 <@valhalla> ad esempio ``grep "(1)" ../dispensa.rst`` vi trova tutti i comandi introdotti di cui si parla in questa dispensa 21:51 <@valhalla> ``grep "(1)" ../../lezione_?/dispensa.rst`` fa più o meno la stessa cosa, in tutte le dispense di questo corso 21:51 <@valhalla> dove il ? viene interpretato dal globbing della shell, mentre grep cerca semplicemente la stringa "(1)" 21:52 <@valhalla> grep stampa poi tutta la riga che soddisfa la ricerca 21:52 <@valhalla> domande? 21:53 <@valhalla> con il semplice grep "(1)" per`o abbiamo visto che trova anche righe che non c'entrano 21:53 <@valhalla> possiamo migliorare la cosa usando alcuni dei caratteri delle espressioni regolari 21:54 <@valhalla> in questo caso, per cercare zero o più caratteri non basta pi`u usare * come prima 21:54 <@valhalla> ma bisogna dire quale carattere e quante volte si ripete 21:54 <@valhalla> ovvero, potremmo dire zero o più ripetizioni del carattere 'a' con ``a*`` 21:55 <@valhalla> che è soddisfato dalle stringhe ``a``, ``aaaaa``, ``aaaaaaaaaaaaa``, ma non da ``bbbbbb`` 21:55 <@valhalla> e poi possiamo comporlo col carattere ``.``, che vuol dire "qualsiasi carattere" 21:56 <@valhalla> altri due caratteri utili nelle espressioni regolari sono ``^`` che indica l'inizio della riga e ``$`` che indica la fine della riga 21:56 <@valhalla> risultato, se noi vogliamo cercare tutte le righe che iniziano per `` seguiti dal nome di un comando, seguito da (1), seguito da ``, possiamo usare: 21:56 <@valhalla> ``grep '^``.*(1)``$' ../../lezione_?/dispensa.rst 21:57 <@valhalla> e con questo (che eventualmente possiamo passare a less aggiungendo in fondo ``| less`` per leggerlo meglio abbiam trovato tutti i comandi di cui si è parlato nel corso 21:57 <@valhalla> domande? 21:57 <@diego71> < JulesX> numero di riga è possibile averlo ? 21:58 <@valhalla> sì, usando l'opzione -n: ``grep -n '(1)``$' ../../lezione_?/dispensa.rst`` 21:58 <@valhalla> altre domande? 22:00 <@valhalla> (vedo che l'ultima riga mi son persa dei pezzi di copincolla, il comando è ``grep '^``.*(1)``$' ../../lezione_?/dispensa.rst`` 22:00 <@diego71> < JulesX> spiegheresti bene la sintassi dell'ultimo comando 22:01 <@valhalla> allora, la prima ed ultima parte sono facili, comando e file su cui cercare :) 22:01 <@valhalla> in mezzo, tra gli '' c'è l'espressione regolare, protetta con '' perché altrimenti la shell farebbe macello dei contenuti, che son pieni di caratteri che per la shell sono speciali 22:01 <@valhalla> il primo carattere dell'espressione regolare è ^, che vuol dire "inizio della riga" 22:02 <@valhalla> poi viene ``, che sono due caratteri che so esserci nelle dispense prima di tutti i nomi di comando 22:02 <@valhalla> poi c'è .*, che significa "qualunque carattere, ripetuto zero o pi`u volte: 22:03 <@valhalla> poi di nuovo dei caratteri specifici che so essere letteralmente presenti nel file: (1)`` 22:03 <@valhalla> e infine $, per dire "fine della riga: 22:03 <@valhalla> cosa che non ho detto, ma è utile dire: grep lavora sulle righe, dall'inizio fino al ritorno a capo 22:04 <@valhalla> non è banale fare ricerche che comprendano testo a cavallo tra le righe 22:04 <@valhalla> altre domande? 22:04 <@valhalla> (e sì, lo so, potevo fare un esempio più facile: questo lo era, poi ho cambiato il formato delle dispense e la versione facile non funzionava più, sorry O:-) ) 22:04 <@diego71> < polva> non ho capito la differenza tra ripetizioni e caratteri. In questo caso tra "?" e "." 22:05 <@valhalla> il significato di *, ? ecc. è diverso tra il globbing (usato dalla shell e da find) e le espressioni regolari 22:05 <@valhalla> nelle espressioni regolari, ? e * si riferiscono al carattere che li precede immediatamente 22:06 <@valhalla> quindi per dire "qualunque carattere, qualunque numero di volte" si deve usare il carattere che vuol dire "qualunque carattere", che è "." 22:06 <@valhalla> e poi metterci il numero di volte, che è "*" (o ? per zero o una ripetizione soltanto) 22:07 <@diego71> erio> ma . e * non danno lo stesso risultato ? 22:08 <@valhalla> no, "." significa soltanto "qualunque carattere" 22:08 <@valhalla> ad esempio l'espressione regolare asd.qwe è soddisfatta da asdxqwe, ma non da asdxxxxxqwe 22:08 <@valhalla> invece asd.*qwe è soddisfatta da entrambe, dato che puoi avere qualunque numero di ripetizioni 22:09 <@valhalla> se invece si mette l'asterisco da solo, asd*qwe in realt`a l'asterisco si riferisce alla "d" che lo precede 22:09 <@valhalla> quindi va bene "asddddddddqwe", ma non pi`u "asdxqwe" 22:09 <@valhalla> altre domande? 22:09 <@diego71> < tiziano> "non è banale fare ricerche che comprendano testo a cavallo tra le righe", ma è possibile (con grep)oppure no? 22:10 <@valhalla> *solo* con grep no, si possono usare dei programmi che tolgano i cambi di riga, e poi dare il risultato in pasto a grep tramite dei | 22:10 <@valhalla> per`o di solito diventa un casino ottenere risultati leggibili, in molti casi 22:10 <@valhalla> altre domande? 22:11 <@diego71> < gioque> ma $ significa fine della riga che sto cercando? cioè se grep cerca sulla riga a cosa serve $ ?? 22:11 <@valhalla> $ serve per dire che non si vuole nient'altro tra l'ultimo carattere scritto e la fine della riga 22:12 <@valhalla> se ad esempio si tolgono ^ e $ dall'espressione di prima, ``grep '``.*(1)``' ../../lezione_?/dispensa.rst`` si trova anche la riga 128 di ../../lezione_1/dispensa.rst 22:13 <@valhalla> che dice "Comandi principali di ``less(1)``" 22:13 <@valhalla> ovvero, non c'è solo "``less(1)``" su quella riga, ma anche dell'altro testo attorno 22:13 <@valhalla> (e noi non volevamo questo caso) 22:13 <@valhalla> altre domande? 22:15 <@valhalla> nel caso in cui le espressioni regolari vi sembrino ostiche, se pu`o consolare c'è un detto: 22:15 <@valhalla> 'Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.' 22:15 <@valhalla> per i casi semplici basta farci la mano e alla fin fine si capisce cosa vogliono dire 22:16 <@valhalla> ma ci si deve fare la mano facendo tante prove 22:16 <@valhalla> altre domande? 22:16 <@diego71> < polva> quindi si potrebbe continuare ad inserire condizioni prima della $ oppure si deve fare un altro "|grep"? 22:17 <@valhalla> polva: dipende da che condizioni si vogliono inserire, s`i, in molti casi è possibile unire tutto in un espressione regolare unica 22:17 <@valhalla> in altri casi, diventa pi`u leggibile passare il risutlato ad un altro grep tramite una pipe 22:17 <@diego71> < polva> e, ditemi se sbaglio, ^ e $ vanno usati sempre l'uno insieme all'altro? o si può fare un uso distaccato? 22:18 <@valhalla> sono totalmente indipendenti, si possono usare o l'uno o l'altro senza problemi 22:19 <@valhalla> gli argomenti della serata sono finiti, quindi se avete altre domande chiedete pure 22:24 <@valhalla> se non ci sono altre domande io chiudo e preparo i log da pubblicare