mercoledì 29 maggio 2013

Termimecum #04
Intro.4 - Introduzione pratica: comandi base


TM#04@Intro.4_Comandi
Nella prima puntata di 'Termimecum' avevo detto che questa rubrica non avrebbe contenuto nessuna pagina in stile "guida base". Ma mi smentisco con questo post :P


La mia "fissa" di fornire un minimo di completezza mi impone di illustrare, anche se veramente "al volo", i comandi base e più utili. Questo perchè mi sono reso conto che, davvero con pochissimo, si può già "indurre" l'utente non avvezzo all'uso della linea di comando ad utilizzarla invece fin da subito, con semplicità ma anche con reali vantaggi pratici.

Ho pensato infatti ad un ipotetico utente che leggesse i primi post sostanziosi (ovvero gli appunti pratici veri e propri) di questa rubrica; essi sono composti solitamente da un solo comando, ma poi?
Senza avere un minimo di dimestichezza col terminale, si finirebbe per usarlo solo per digitare una linea, per poi dover "tornare" alla shell grafica, poi magari ritornare a terminale e così via, perdendo buona parte del vantaggio acquisito dalla potenza della linea di comando.

Invece, con una conoscenza davvero basilare dei comandi, è possibile fin da subito destreggiarsi nella shell (non grafica); e questo, per chi avrà il "coraggio" di provare, vedrete che sarà di grande utilità.


  • Comandi di visualizzazione
Cominciamo coi comandi che ci permettono di visualizzare informazioni e file.
Il comando informativo per eccellenza è il vero vademecum del terminale e dei comandi unix in generale, man:

(i01) $ man [SEZIONE] {COMANDO}

'man' è una vera e propria "enciclopedia dei comandi". Vi basterà dunque scrivere 'man' seguito dal nome del comando su cui volete informazioni e vi apparirà la guida di tale comando. Le sezioni sono numeri, da 1 a 9, usati per identificare i diversi ambiti di competenza dei comandi. Infatti 'man' contiene sia comandi della shell che chiamate di sistema, così come file di gestione particolari, librerie di programmazione, ecc...
Per i nomi "ambigui", quindi per quelle istruzioni che presentano più di un ambito di lavoro, è possibile specificare la sezione particolare su cui si vuole informarsi.
Per avere la lista precisa delle sezioni ed ulteriori informazioni su 'man', non dovete far altro che leggere il manuale di man:

$ man man


Passiamo ora al "lavoro" vero e proprio...

La prima cosa che conviene sapere è dove "ci troviamo". Normalmente il prompt è formattato in modo da mostrare la directory attuale, se non l'intero percorso; ma per ogni evenienza...

(i02) $ pwd

Non fa altro che mandare in output la directory corrente, con percorso completo.

Per visualizzare il contenuto della directory:

(i03) $ ls [-a[g|l[h]]rRStxX] [--color[=never|=always|=auto]] [PATH|FILE]
-a visualizza anche i file nascosti
-g mostra una versione listato
-l versione listato più estesa, mutuamente esclusiva con la precedente
-h usabile con '-g' e '-l', visualizza le dimensioni dei file in formato più leggibile
-r inverte l'attuale ordinamento dell'output
-R visualizzazione ricorsiva (mostra il contenuto di tutte le sottodirectory)
-S ordina l'output per dimensione
-t ordina l'output per data di modifica
-x mostra l'output per righe invece che per colonne
-X ordina l'output per estensione (se presente)
--color stabilisce se e quando visualizzare l'output con la colorazione
Ricordate che, se non altrimenti specificato, le opzioni di comando sono cumulabili, per cui è possibile scrivere cose del tipo:
ls -alhR

Scrivendo semplicemente 'ls' visualizzerete il contenuto della directory corrente; se specificherete invece un determinato percorso, visualizzerete il contenuto della directory interessata; se, infine, specificherete un preciso file, visualizzerete esclusivamente quel file, se esiste.
L'ultima possibilità è utile per verificare velocemente l'esistenza di un file all'intero di una directory molto "affollata" e/o visualizzare (con le opzioni '-l' o '-g') caratteristiche e permessi.
Ricordatevi sempre del "trucchetto" del completamento col tasto [TAB], utilissimo ogni qualvolta dobbiamo scrivere nomi di percorsi, directory o file.


  • Visualizzazione di file
Si rende a questo punto necessario affrontare il tema della paginazione del testo. E' possibile per testi e listati lunghi, come nel caso dell'output di un 'ls' dato in una directory piena zeppa, avere una forma di paginazione tipo quella di 'man'?
Ovviamente sì; il metodo più utilizzato ricorre ad altri due comandi, più o meno intercambiabili: more e less

(i04) $ more [-d] {PATH|FILE}
(i05) $ less {PATH|FILE}
-d del comando more visualizza un "prompt esteso" a fondo schermo
'more' è il programma storico per questo utilizzo, mentre 'less' è più recente e quindi con qualche features in più. In particolare, 'less' consente l'uso delle freccie direzionali e dei tasti di scorrimento pagina, cosa che lo rende generalmente preferibile.
Per entrambi i comandi: durante l'utilizzo, ovvero mentre si sta leggendo il file in ingresso, è possibile visualizzare la lista dei comandi premendo il tasto [h] ed è possibile uscire con il tasto [q]
Quindi, se nell'attuale directory abbiamo un file (abbastanza lungo da occupare più di una schermata) chiamato 'pippo.txt' e scriviamo:
more pippo.txt
visualizzeremo il contenuto del file con la possibilità di scorrere una pagina alla volta.

Tutto ciò sembrerebbe non essere d'aiuto nel caso di output di comandi, il problema posto dal precedente quesito su 'ls'; ma è solo perchè dobbiamo parlare ancora delle pipeline.
Una pipeline è una "concatenazione di comandi". In pratica, una serie di comandi nella quale l'output del primo comando finisce nell'input del secondo, il cui output diventa a sua volta input del terzo (eventuale), ecc... Vedremo più avanti che questo "giochetto" e possibile in parte farlo anche manualmente, ma è più complicato e bisogna utilizzare dei file di appoggio.
Per farlo invece in modo semplice e trasparente dobbiamo utilizzare la sbarretta verticale [|] tra un comando e l'altro. Quindi, nel caso del "nostro" 'ls' avremo (per esempio):
ls -gh | more
Come detto, l'output di 'ls' che abbiamo posto di una directory molto piena, finirà in input a 'more' e di conseguenza ci apparirà "paginato" e comodo da leggere.
Un'ultima, accessoria, considerazione su questo uso dei comandi 'ls' e 'more'/'less'. Utilizzando la pipe sopra esposta si perde la colorazione (solitamente impostata su 'auto' nel file di configurazione standard). E' possibile "forzarla" con l'opzione '--color' nel seguente modo:
ls -al --color=always | less
Avete provato? Scherzetto :P
L'output che visualizzate con quel comando appare "sfrancato" da segni strani. Questo perchè 'less' non interpreta determinati flag come fa invece 'more'; ovvero 'less' lavora ad un livello leggermente più basso rispetto a 'more'. Questo è utile in alcuni casi ma quantomeno fastidioso in altri, come quello proposto. E' per questo motivo che il mio consiglio (molto personale e generico) è quello di utilizzare 'less' quando si ha a che fare con file, mentre conviene usare 'more' per trattare l'output di altri comandi.

Ho trattato i precedenti comandi per primi perchè mi sono ricollegato al problema dell'output di 'less'. Ma in realtà il comando "base" per la visualizzazione di file, quello che manda in output il file intero senza alcuna paginazione, è cat


Però ne scrivo più che altro per "conoscenza storica"; i comandi di cui abbiamo parlato, oppure i programmi di gestione file per terminale (che vedremo più avanti) sono sicuramente più comodi e potenti.
Diciamo che è un sistema comodo e veloce per visualizzare file che sappiamo di una (o poco più) riga. Anche perchè, in realtà, il termine "cat" sta per "concatenate"; in effetti a questo serve il comando, a concatenare file e dare il risultato in output. Vedremo che non è l'unico caso nel quale un "effetto collaterale" di un comando porta ad un uso "autonomo" ed alternativo del comando

Una delle esigenze che si presenta nell'uso del terminale è quella di leggere solo la parte iniziale o solo quella finale di un file: per esempio, molti file di configurazione vengono editati nelle ultime righe, che poi magari si vogliono ricontrollare; oppure vi sono file che sappiamo presentare "punti cruciali" nelle prime righe; ecc...
Per queste due eventualità vi sono i comandi 'head' e 'tail', per le prime 10 righe e le ultime 10, rispettivamente

(i07) $ head [-<n>] [PATH|FILE]
(i08) $ tail [-<n>] [PATH|FILE]

L'opzione '-<n>'(con n=numero naturale) consente di specificare il numero preciso di righe da visualizzare, altrimenti assunto per default pari a 10.
Allo stesso modo di 'less', anche questi due comandi possono essere utilizzati in una pipeline (effettivamente tutti i comandi hanno questa possibilità, ma non per tutti è sensato).
Ad esempio, per visualizzare le ultime 3 righe del file di log dmesg:
dmesg | tail -3



  • Cambiare directory e piccole utilità
Anche se la maggior parte dei comandi che lavorano su file ammette la specificazione del percorso, quindi in teoria consentono di lavorare su qualsiasi file a prescindere dalla directory corrente, è evidente che sarebbe alquanto fastidioso rimanere relegati alla sola directory 'home'.
Per poter "navigare" all'interno del filesystem esiste il comando 'cd'

(v02) $ cd [PATH|..|-]
.. consente di risalire alla directory madre
- riporta alla directory nella quale eravamo precedentemente
Il comando senza alcun parametro riporta alla 'home'; equivale a 'cd ~' e 'cd /home/<USERNAME>'. Il comando col doppio punto '..' funziona esattamente come nel DOS di Winzozz, ma ricordatevi di mettere lo spazio tra il comando ed i due punti!

Dopo tante prove ci troviamo la console piena di roba. Come facciamo a cancellare lo schermo e tornare ad averlo bello pulito? Presto detto

(v03) $ clear


Un comando molto più profondo, che porta ad una vera a propria re-inizializzazione della sessione, è

(v04) $ reset

E' utile in diverse situazioni. Per esempio, se si dovesse leggere per sbaglio un file non leggibile, che contiene caratteri che vengono interpretati e, di conseguenza, ci si ritrovasse al "buio" (tasti che non corrispondono, cursore sparito, ecc...), allora digitare 'reset' può tornarci utile.
;)


  • Gestire file e directory
Passiamo a lavorare su file e directory. Mi rendo conto che sembra tutto molto anacronistico, con l'interfaccia grafica è un attimo creare una directory o spostare gruppi di file; perchè dovremmo sbatterci a farlo da tastiera?
Per quanto dicevo all'inizio. Magari siamo lì ad eseguire un compito che si svolge ottimamente da terminale, ma sul più bello dobbiamo spostare o rinominare un file. Allora dobbiamo aprire il gestore grafico, andare a cercare la directory sulla quale stiamo lavorando, trovare il file, poi tornare al terminale... insomma, fidatevi, è molto più pratico fare tutto da tastiera :)

A volte, soprattutto per prove e/o file di "appoggio", può servire di creare un file "al volo", anche se vuoto. Per questo compito si può usare il comando 'touch'

(f01) $ touch {(PATH)FILE|LIST_(PATH)FILE}

In realtà 'touch' serve per modificare la data di un file esistente; ma siccome se il file non esiste viene creato, alla fine è "diventato" il comando per la creazione di file "al volo" per eccellenza.
Come potete vedere è anche possibile creare più file in un colpo solo, basta elencarne i nomi separati da uno spazio; molto utile quando si ha la necessità di fare prove "massive".

Per copiare un file si usa il comando 'cp'

(f02) $ cp [-b[f|i|n]rsuv] [SOURCE_(PATH)FILE] [TARGET_(PATH)FILE]
-b crea una copia di backup del file
-f forza la sovrascrittura di un eventuale file già esistente
-i chiede conferma per la sovrascrittura, in caso TARGET sia già esistente
-n impedisce la sovrascrittura di un eventuale file già esistente
-r copia ricorsivamente, necessario per copiare intere directory
-s non crea una vera e propria copia, ma un link simbolico
-u copia il file solo se TARGET non esiste o se questo è più vecchio di SOURCE
-v visualizza l'output esteso (verbose)
Quanto sopra sintetizza l'uso basilare del comando. Vi è anche la possibilità di copiare più file per volta in una directory e altro; per ulteriori informazioni, come al solito, fate riferimento alla pagina di 'man'.
Per spostare e rinominare i file si usa un solo comando: 'mv'
Le lettere di opzione illustrate sono tutte in comune con 'cp', ed hanno la medesima funzione

(f03) $ mv [-b[f|i|n]uv] [SOURCE_(PATH)FILE] [TARGET_(PATH)FILE]

Se non si specifica alcun percorso, o se i percorsi di SOURCE e TARGET coincidono, il comando rinomina il file SOURCE con il nuovo nome specificato in TARGET.
Se invece si specificano diversi percorsi (o anche solo uno dei due, quello non specificato è inteso come la directory corrente), il comando sposta il file SOURCE nel percorso TARGET.
Faccio un esempietto giusto per scrupolo. Supponiamo di essere nella directory 'home', che contiene il file 'pippo.exe'; lo rinomino in 'pluto.sh':
mv pippo.exe pluto.sh
mentre ora (col suo nuovo nome) lo voglio spostare nella directory '/usr/bin/'
mv pluto.sh /usr/bin/
Se abbiamo la necessitò di eliminare un file dobbiamo usare il comando 'rm'
Anch'esso ha, nel nostro caso, lettere d'opzione uguali ad alcune di 'cp' e con medesimo effetto

(f04) $ rm [-[f|i]rv] {(PATH)FILE|LIST_(PATH)FILE}

Come potete vedere è possibile eliminare un solo file o anche più file alla volta, elencandoli uno di seguito all'altro separati da uno spazio. Ricordo che l'opzione '-r' consente la ripetizione ricorsiva, ovvero l'eliminazione delle directory.
ATTENZIONE: che sia o meno interattivo (opzione '-i': chiede conferma ad ogni eliminazione), una volta eseguito il comando NON ha alcun meccanismo tampone: il file è eliminato definitivamente! Dico questo perchè, abituati ai DE e ai loro "cestini", è facile rischiare di fare danni se si prende il comando troppo "alla leggera".
Magari, a questo proposito, più avanti in 'Termimecum' farò un esempio di scriptino che crei un comando di cancellazione che usi un "cestino" di sicurezza.

Infine i comandi per la gestione delle directory.
Per creare una directory:

(f05) $ mkdir [-pv] {(PATH)DIR|LIST_(PATH)DIR}
-p crea le "directory genitrici" specificate nel percorso, se non esistono
-v visualizza l'output esteso (verbose)
Per eliminare una directory vuota:

(f06) $ rmdir [-pv] {(PATH)DIR}
-pelimina anche le "directory genitrici" specificate nel percorso
-v visualizza l'output esteso (verbose)
Purtroppo 'rmdir' funziona solo con directory vuote. Per cui, se la directory che volete eliminare contiene dei file - e ovviamente se davvero questi non vi servono! - potete: eliminare prima tutti i file e dopo operare con 'rmdir'; oppure, più semplicemente, utilizzare 'rm -r <DIR_NON_VUOTA>'.
Se state pensando che sia una complicazione non necessaria, sono d'accordo con voi. Sarebbe bastata un'opzione ulteriore nel comando 'rmdir', da dover aggiungere nel caso di directory piene. Ma bho, è così :|


Dopo questa "sfacchinata" non è che vi dovete spaventare... alla fine tutto così insieme sembra una paccata di roba, ma in realtà i comandi sono semplici e veloci.
Ovviamente, come detto all'inizio, nella "quotidianità" si può fare tutto da interfaccia grafica e addio scritte noiose. Ma vi assicuro che, superato l'approccio iniziale, finirete per apprezzare davvero tanto la basilarità e potenza del terminale.

Nessun commento:

Posta un commento