Word e LaTeX a confronto

Macchinetta del caffè. C’è anche un collega, simpatico, divertente, con un passato piuttosto “vissuto”, uno dei migliori colleghi con cui trascorrere la fatidica pausa caffè di metà mattinata.1 A un certo punto inizia a raccontare di quando, da “giovane”, aveva dovuto usare LaTeX per scrivere, di quanto poco gli piacesse e di come trovi Word infinitamente più comodo da usare.

Io dico qualcosa, parlo di riferimenti incrociati, di equazioni, di bibliografia, roba semplice, non mi azzardo a toccare aspetti più sofisticati, semantica, separazione fra aspetto grafico e contenuto, formato dei file e compatibilità futura. Non ho voglia e tantomeno tempo di discutere, tanto so già che non c’è verso di convincerlo, per lui Word è la modernità, il progresso, LaTeX è un reperto archeologico da mettere in soffitta.

Per puro caso, lo stesso giorno mi decido a leggere questo articolo, Weighted differential evolution algorithm for numerical function optimization, che avevo messo da parte da mesi. L’articolo non solo non è un granché, ma è anche impaginato in modo orrendo. Leggere è così fastidioso che non riesco nemmeno a concentrarmi sul contenuto.

C’è chiaramente lo zampino di Word. Il massimo dell’orrore è in questa mezza colonna…

un paragrafo scritto in Word con gli errori più gravi messi in evidenza
Fig. 1. Esempio di articolo scientifico scritto in Word. A sinistra l’immagine originale di una breve sezione dell’articolo, a destra la stessa immagine con gli errori più gravi messi in evidenza.

Non sono esperto di grafica, ma salta all’occhio perfino a me che la resa finale è sciatta e poco professionale. Nell’immagine a destra ho provato a segnare gli errori più marchiani in ordine (personale) di importanza, (1) la spaziatura eccessiva fra le parole, (2) le formule matematiche inconsistenti, (3) gli spazi arbitrari all’inizio della riga, ma sono sicuro di non essermi accorto di qualche altro e(o)rrore. Ho anche messo in evidenza in giallo due formule con spaziature differenti del segno di “=” (la seconda è sbagliata).

E allora ho voluto provare cosa veniva fuori con LaTeX. Ho scaricato dal sito della rivista che aveva pubblicato l’articolo il package per LaTeX e ho riscritto l’articolo con quello che tanti (non solo il mio collega) considerano solo un reperto archeologico.

Il risultato, considerando solo la sezione incriminata, è qui sotto, a sinistra si può vedere l’originale in Word, a destra l’equivalente in LaTeX con le marcature corrispondenti ai vari “errori” di Word (le stesse immagini senza marcature sono disponibili qui).

confronto fra Word e LaTeX
Fig. 2. Confronto fra Word e LaTeX. A sinistra l’immagine dell’articolo originale in Word, a destra la stessa sezione riscritta in LaTeX.

Tengo a precisare che non ho fatto niente per “aggiustare” l’output di LaTeX (infatti il numero dell’equazione è sbagliato), mi sono limitato ad usare lo stile fornito dalla rivista, che utilizza dei font differenti da quelli con cui vengono impaginati gli articoli pubblicati, probabilmente perché sono di proprietà della casa editrice (Springer).

Ma, a parte al questione font, il confronto fra Word e LaTeX è impietoso: LaTeX riesce a spaziare le parole senza creare “buchi” antiestetici, le righe sono allineate perfettamente, le formule sono scritte in modo consistente e gradevole da vedere, che rende più facile capirne il significato. Anche l’unica equazione fuori testo ha quel tanto di spaziatura dal resto del testo che riesce a metterla in evidenza, come è giusto che sia.

Niente male per un software “vecchio” da mettere in soffitta, sviluppato solo perché all’autore non piaceva come era stato impaginato il suo ultimo libro.


  1. Da oggi in effetti è un ex-collega. 
Annunci
Tagged with: , ,
Pubblicato su software

Come usare Skype Web con Safari e Firefox

Uso pochissimo Skype, per comunicare o condividere file con amici o colleghi preferisco di gran lunga usare Slack. Per cui, quando ho letto che la nuova versione di Skype utilizzabile via browser rilasciata la settima scorsa supportava solo Edge e Google Chrome — rispettivamente il nuovo browser Microsoft che l’azienda di Seattle cerca disperatamente di far usare a qualcuno e il browser dominante con il quale non si può non fare i conti — ho scrollato le spalle e sono passato ad altro.

Ma dopo aver perso tutta la mattina per far funzionare di nuovo la mia installazione di Office per Mac dopo un banale crash di Excel, ho il dente avvelenato con Microsoft. E quando mi è capitata di nuovo sotto sgli occhi la notizia dell’incompatibilità di Skype Web anche con browser molto diffusi come Firefox o Safari, ho voluto provare di persona. E in effetti, se si prova ad aprire Skype Web con uno di questi browser, si ottiene l’ormai ben nota schermata di “Browser not supported”.


Fig. 1. Accesso a Skype Web “visto” da Safari.


Fig. 2. Skype Web “visto” da Firefox.

Sembra si essere tornati ai tempi dei siti “Ottimizzati per Internet Explorer”, che più che ottimizzati erano solo codificati in modo sciatto.

E proprio come succedeva ai tempi del famigerato Internet Explorer, con un trucco semplicissimo è possibile rendere Safari o Firefox (ma di sicuro anche Opera o qualunque altro browser moderno) pienamente compatibili con la versione web di Skype.

Il trucco è banale, basta accedere a Skype Web fingendo di usare Edge o Chrome. La chiave di tutto sta nello User Agent, una stringa di testo che il browser invia al server ogni volta che accede ad una pagina web, che contiene fra l’altro il nome e la versione del browser e del sistema operativo in uso.

Lo User Agent della mia versione di Safari per macOS è

Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.3 Safari/605.1.15

mentre quello di Firefox è

Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:65.0) Gecko/20100101 Firefox/65.0

Lo User Agent inviato dal browser non è scolpito nel marmo, anzi si può modificare piuttosto facilmente, ed è proprio quello che faremo per accedere a Skype Web da un browser non supportato.

Safari

Per modificare lo User Agent in Safari bisogna prima di tutto selezionare le Preferenze del browser, cliccare sul pannello Avanzate e attivare l’opzione Mostra il menu Sviluppo nella barra dei menu.


Fig. 3. Preferenze avanzate di Safari.

Una volta tornati alla finestra principale del browser, si clicca sulla nuova voce di menu Sviluppo, poi su User Agent per selezionare infine nella lista che compare Google Chrome o Microsoft Edge. Se ora si prova ad accedere a Skype Web, al posto dell’avviso “Browser not supported” compare la solita finestra di login della Microsoft, basta inserire i propri dati ed è fatta.



Fig. 4. Ora Skype Web è accessibile da Safari.

Firefox

Per modificare lo User Agent in Firefox non è possibile utilizzare le funzioni native del browser e quindi il processo è leggermente più complicato. Ma Firefox ha add-on per (quasi) tutto, e fra questi gli add-on che modificano lo User Agent non mancano di certo.

Io uso User-Agent Switcher che funziona senza problemi ed è molto configurabile (fin troppo!), ma qualunque add-on analogo va altrettanto bene. Una volta installato User-Agent Switcher, sulla barra principale di Firefox compare l’icona di un omino con il cappello, basta cliccarci sopra per far comparire una lunghissima(!) lista di User Agent fra cui scegliere.


Fig. 5. La lista, fin troppo dettagliata, di User Agent supportati da User-Agent Switcher.

A questo punto basta selezionare lo User Agent di una delle ultime versioni di Edge o di Chrome e cliccare su Apply. Se ora si prova ad accedere a Skype Web, ci si troverà davanti la finestra di login della Microsoft e, come già visto per Safari, una volta inseriti i propri dati si potrà usare Skype Web anche con Firefox.


Fig. 6. Ora Skype Web è accessibile anche da Firefox.

Conclusioni

Rendere una applicazione web compatibile solo con alcuni browser è una mossa incomprensibile, anche perché taglia fuori una fetta più o meno larga di utenti del web.1

Ma una volta risolto il problema della compatibilità di Skype Web con i browser non supportati ufficialmente da Microsoft, rimane il problema di fondo: ha senso continuare ad usare un programma come Skype che, se agli inizi era un prodotto innovativo, una volta passato nelle grinfie di Microsoft è peggiorato visibilmente, diventando ad ogni nuova iterazione sempre più grosso, pesante e poco pratico? Le alternative ci sono, perché non provare a cambiare?


  1. Ancora meno comprensibile è che si possa aggirare il blocco così facilmente, non posso credere che gli sviluppatori Microsoft non conoscano questi trucchi banali. 
Tagged with: , , , , , , ,
Pubblicato su software

WorldWideWeb, il primo browser web è online

La storia la sapete. Trent’anni fa Tim Berners-Lee, un fisico del CERN, sviluppò su un computer NeXT il primo server web httpd e il relativo browser, che chiamò WorldWideWeb,1 insieme al linguaggio HTML con cui creare i documenti ipertestuali visualizzabili dal browser.

Tim Berners-Lee non aveva idea che il suo lavoro avrebbe rivoluzionato la nostra vita. In realtà voleva solo permettere di preparare dei documenti collegati uno all’altro da utilizzare all’interno del CERN, rendendo possibile passare da un documento all’altro cliccando sui link presenti nei documenti stessi.

Un’idea nemmeno troppo nuova, il concetto di ipertesto era stato introdotto da Ted Nelson già a metà degli anni ’60 ed era stato reso popolare da Apple con il suo linguaggio HyperCard.

Il primo sito web sviluppato Tim Berners-Lee è ancora online, ed è un’ottimo modo per accedere ai documenti originali che sono alla base del web come lo conosciamo oggi.

Ora, per celebrare il trentesimo anniversario del web, il CERN ha messo online un emulatore del browser WorldWideWeb originale scritto da Tim Berners-Lee, che gira tranquillamente all’interno di un qualunque browser odierno. L’esperienza d’uso di WorldWideWeb è infinitamente meno soddisfacente di quello a cui siamo abituati oggi, ma vale la pena provare in prima persona una tecnologia che ha avuto effetti straordinari e assolutamente imprevedibili sulla vita di tutti noi. Anche se non ci sono le immagini, i siti odierni sono ancora perfettamente fruibili, sembra di usare un browser testuale come Links o Lynx. L’unica accortezza è ricordarsi che per attivare i link c’è bisogno di un doppio click, il click singolo a cui siamo abituati arriverà solo qualche tempo dopo.

E allora perché non provare a leggere questo blog tramite il browser originale di Tim Berners-Lee? Io ci ho provato, e non è nemmeno troppo difficile. Basta lanciare l’emulatore di WorldWideWeb, cliccare sulla voce Document del menu laterale e poi su Open from full document reference. A questo punto bisogna scrivere (o incollare) nel campo Reference l’indirizzo web completo di melabit, https://melabit.wordpress.com, e cliccare sul grosso (e brutto) bottone Open di destra. Quello che succede si può vedere qui sotto (cliccando sulle immaginini si aprono le versioni in alta risoluzione).





Niente immagini e niente colori, i caratteri speciali vengono resi con i codici HTML (l’apostrofo ad esempio diventa ’), il font è quello ancora pixellato del NeXT, cliccando sui link si aprono delle nuove finestre invece che nuove schede come nei browser moderni, la barra di scorrimento della finestra è a sinistra e non a destra come siamo abituati ora. Però a parte queste minuzie, il blog è perfettamente fruibile, anche se stiamo usando uno strumento pensato e sviluppato ben trent’anni fa.

Affascinante.


  1. Da cui deriva la tripletta “www”, utilizzata da allora per indicare il web. 
Tagged with: , , , , , , , , , ,
Pubblicato su software

Script per tutti i giorni: entra in scena awk


Tastiera A.W.K., Viscount Instruments.

Nelle prime tre puntate di questa serie abbiamo imparato a scrivere uno script in bash per trasformare una stringa di testo in modo che segua delle convenzioni ben determinate a priori (qui i link alla prima, seconda e terza puntata).

In questo caso particolare, la stringa risultante dalla trasformazione deve essere scritta tutta in minuscolo e non deve contenere apostrofi o altri caratteri speciali, a parte il trattino usato come separatore di parole. L’idea è quella di usare questa stringa, insieme alla data di pubblicazione del post, per dare un nome standard e facilmente rintracciabile al file Markdown che contiene il testo del post stesso, utilizzando il formato YYYY-MM-DD-titolo-del-post.md, dove YYYY indica l’anno, MM il mese e DD il giorno di pubblicazione.

L’approccio seguito finora è utile per imparare i fondamenti della programmazione in bash, ma manca decisamente di praticità. Partire dal titolo e dalla data di pubblicazione presenti nell’intestazione del post per arrivare al nome completo del file richiede un certo lavoro di copia e incolla fra l’editor, il Finder e il Terminale, e gli errori sono sempre in agguato.

Quello che ci vuole è uno script che renda il processo completamente automatico, rinominando il file Markdown a partire dal contenuto del documento stesso.1

Si potrebbe benissimo fare anche con bash, ma perché complicarsi la vita quando c’è uno strumento fatto apposta per analizzare ed estrarre dei dati dai file di testo?

AWK, questo sconosciuto

AWK è un linguaggio di programmazione interpretato sviluppato negli anni ’70 presso i Bell Labs, il famosissimo centro di ricerca americano che ci ha dato il transistor, il laser, Unix e il C (e moltissimo altro). AWK è stato sviluppato da Alfred Aho, Peter Weinberger e Brian Kernighan, tre grandi studiosi di computer science, fra i quali spicca il terzo, coautore insieme a Dennis Ritchie di The C Programming Language, il volume di riferimento sul linguaggio C, noto anche semplicemente come “K&R” dai cognomi dei due autori.

Alla base di AWK c’è l’idea di elaborare un file di testo una riga alla volta, controllando che la riga in esame soddisfi una o più condizioni prestabilite ed eseguendo le azioni programmate per ciascuna di queste condizioni

    condizione #1: {azione #1}
    condizione #2: {azione #2}
    ...
    condizione #N: {azione #N}   

Per AWK un file di testo è costituito da un certo numero di righe (record), ciascuna delle quali è suddivisa in uno o più campi (field), separati fra loro da un separatore di campo, che di default è lo spazio ma che può essere modificato a piacere. Per riferirsi a ciascun campo AWK usa le variabili speciali $1, $2 e così via, dove il numero indica la posizione del campo all’interno della riga. La variabile $0 contiene l’intera riga corrente.

Tutto qui? Più o meno. C’è (quasi) solo da aggiungere che AWK prevede due azioni speciali opzionali, racchiuse fra i blocchi BEGIN {...}, END {...}, che servono per eseguire le operazioni preliminari e conclusive necessarie per il buon funzionamento del programma, ad esempio per definire il separatore di campo. Un programma completo in AWK ha quindi una struttura di questo tipo,

    BEGIN { istruzione
            istruzione
            ....
          }

    condizione #1: { istruzione
                     istruzione
                     ....
                   }
    condizione #2: { istruzione
                     istruzione
                     ....
                   }

    ...
    condizione #N: { istruzione
                     istruzione
                     istruzione
                     ....
                   }

     END { istruzione
           istruzione
           ....
         }

dove come già detto i blocchi BEGIN {...}, END {...} sono opzionali.

Nonostante la fama dei suoi autori, AWK è poco utilizzato, molto meno di quanto meriterebbe, i programmatori del mondo UNIX preferiscono usare strumenti più semplici ma meno potenti come sed (che abbiamo già incontrato nelle puntate precedenti) o il declinante perl, un linguaggio di manipolazione di file di testo perfetto per i programmatori che mitizzano Tafazzi.

AWK invece ha il giusto equilibrio di potenza e semplicità d’uso ed è uno strumento perfetto se gli si chiede di fare quello per cui è stato ideato, elaborare informazioni strutturate contenute in file di testo.

Per fortuna AWK è installato di default in macOS e in Linux, oltre che in tutti i sistemi operativi basati su UNIX che si trovano in giro, per cui per provarlo basta lanciare il Terminale ed eseguire il comando awk. In realtà ci sono in giro almeno due versioni diverse di AWK. In macOS è installato awk liscio, la versione del linguaggio definita dai tre autori originali nel volume The AWK programming language. Su Linux, invece, si trova in genere gawk, una implementazione del linguaggio della Free Software Foundation pienamente compatibile con awk, a cui sono state aggiunte alcune estensioni piuttosto utili. Installare gawk su macOS è facile per chi usa Homebrew, dal Terminale

$ brew install gawk

Da ora in poi per semplicità farò cadere la distinzione fatta finora fra AWK, il linguaggio di programmazione, e awk, l’interprete del linguaggio, usando sempre e solo il termine awk per riferirmi ad entrambi.

Un programma banale in awk

Per avere una idea di cosa può fare awk, ecco un piccolissimo (e rozzo) programma di esempio,

BEGIN { FS = ","
        OFS = ", "
      }

$1 ~ /Violanda/ { $1 = "Jolanda" }
                { print $2, $1, $3, $6, $4, $5 }

che applicato ad un elenco di indirizzi come questo,

NOME,COGNOME,INDIRIZZO,LOCALITA,PROVINCIA,CAP
Massino,Nardini,Via Roma 8,Grana,AT,14031
Primo,Sabbatini,Via C. Cattaneo 50,Cala di Volpe,SS,07020
Giuseppe,Marino,Via C. Alberto 75,Barni,CO,22030
Ivano,Costa,Via Guantai Nuovi 29,Ischia,NA,80077
Margherita,Davide,Via Nuova Agnano 83,Rufina,FI,50068
Daphne,Lettiere,Via R. Conforti 67,Castel Di Ieri,AQ,67020
Violanda,Lori,Via A. Manzoni 101,Parona,PV,27020
Luigia,Cremonesi,Via Castelfidardo 145,Cittadella Del Capo,CS,87020
Fiore,Mucciano,Via Valpantena 120,Buccino Stazione,SA,84020
Sandra,Greco,Via Pisanelli 140,Castiglione D'Adda,LO,26823

scambia la posizione del nome e del cognome e sposta il CAP prima della Località in tutte le righe del file. Già che c’è, corregge anche il nome sbagliato “Violanda” e lo trasforma in “Jolanda”. Nella riga #5, $1 ~ /Violanda/ è la condizione, e {$1 = "Jolanda"} l’azione relativa, mentre nella riga #6 la condizione è vuota e quindi l’azione conseguente {print $2, $1, $3, $6, $4, $5} si applica a tutte le righe del file. Il blocco BEGIN {...} serve per definire il carattere (o i caratteri) che separa i campi contenuti in ciascuna riga letta o scritta dal programma: la variabile predefinita FS è il separatore dei campi del file di input (quello letto dal programma), OFS è il separatore dei campi delle righe stampate dallo script.

Per provarlo, copiate il programma in un editor e salvatelo come swap.awk, poi copiate la lista di indirizzi e salvatela come address.csv (meglio se salvate i due file nella cartella ~/Development, ricordate?). Infine lanciate il Terminale, eseguite il comando

$ awk -f swap.awk address.csv 

e vedete cosa viene fuori. Provate a cambiare OFS e a vedere che succede.

Domanda 1: Come si fa a lanciare lo script senza dover premettere il comando awk?

Domanda 2: Se si rimuove la variabile FS dal blocco BEGIN{...} lo script continua a funzionare correttamente?

Ma basta con awk. Questo articolo non vuole essere una introduzione al linguaggio ma vuole solo mostrare come si può risolvere con AWK il problema che ci sta a cuore. Chi volesse è approfondire la conoscenza del linguaggio può consultare i volumi e le guide online riportate in bibliografia.

Rinominare automaticamente un post

E finalmente eccoci al programma awk che rinomina da solo il file Markdown di un post in base al titolo e alla data contenuti nei metadati del documento, che contengono, fra l’altro, il titolo, la data di pubblicazione, la categoria e i tag associati al post stesso.

BEGIN { FS = " "
        OFS = "-"
        EXT = ".md"
      }

$1 ~ /[Dd]ate:/   { date = $2 }
$1 ~ /[Tt]itle:/  { title = ""
                    for (i = 2; i <= NF; i++) {
                        title = title FS tolower($i)
                    }
                  }

END { newfilename = date OFS title
      gsub("[[:cntrl:]]", "", newfilename)
      gsub("[\"]+", "", newfilename)
      gsub("[\.,;:!\?&\$]+", "", newfilename)
      gsub("[-| ]+", "-", newfilename)
      newfilename = newfilename EXT
      system("mv " FILENAME " " newfilename)
    }

Riassumo brevemente cosa fa il programma, chi non fosse interessato può saltare direttamente al prossimo paragrafo. La prima condizione $1 ~ /[Dd]ate/ cerca la stringa date: (indifferentemente in minuscolo o maiuscolo) nel primo campo di tutte le righe del post e quando la trova assegna il secondo campo, corrispondente alla data, alla variabile date.
La seconda condizione fa lo stesso per il titolo e lo assegna alla variabile title. Poiché il titolo è distribuito su un numero imprecisato di campi (ricordo che il separatore di campo FS è lo spazio), viene utilizzato un ciclo for per leggere ed aggiungere in successione a title tutti i campi della riga successivi al primo. Il numero di campi presenti nella riga del titolo è contenuto nella variabile di sistema NF, aggiornata automaticamente dall'interprete ogni volta che viene letta una nuova riga.
La parte finale del programma, racchiusa nel blocco END {...}, si occupa di definire la variabile newfilename, contenente il nuovo nome da assegnare al file, e di trasformarla secondo le regole desiderate.
La variabile newfilename contiene inizialmente (riga #12) la data e il titolo letti nel post, separati da un trattino (il valore di OFS). Nelle quattro righe successive viene utilizzata la funzione gsub per rimuovere da questa variabile tutti i caratteri indesiderati (caratteri di controllo, virgolette, punteggiatura) e per sostituire spazi e trattini (anche multipli) con un trattino singolo. Alla riga #17 viene aggiunta l'estensione definita in EXT, mentre l'ultima riga del blocco effettua una chiamata al sistema operativo per rinominare effettivamente il file, utilizzando un'altra variabile di sistema, FILENAME, che contiene il nome originale del file Markdown su cui sta operando lo script.

Salviamo il programma nella solita cartella Development con il nome setpostname.awk. Per provarlo dobbiamo avere anche un file Markdown contenente nell'intestazione (header) almeno i metadati relativi al titolo e alla data. Possiamo prendere la prima parte di questo post,

---
layout: post  
title: "Script per tutti i giorni: entra in scena awk"  
author: Sabino Maggi  
date: 2019-02-18 18:00  
categories:  
  - programmazione  
tags:  
  - awk  
  - bash  
  - editor  
  - gawk  
  - perl  
  - script  
  - terminale  
comments: true  
published: true  

---

Nelle prime tre puntate di questa serie abbiamo imparato a scrivere uno script in `bash` per trasformare una stringa di testo in modo che segua delle  convenzioni ben determinate a priori (qui i link alla [prima](https://melabit.wordpress.com/2018/11/23/script-per-tutti-i-giorni-semplici-modifiche-alle-stringhe-di-testo/), [seconda](https://melabit.wordpress.com/2018/12/05/script-per-tutti-i-giorni-dalla-linea-di-comando-al-programma/) e [terza](https://melabit.wordpress.com/2018/12/30/script-per-tutti-i-giorni-shell-e-parametri/) puntata).

In questo caso particolare,...

e salvarlo con un nome qualsiasi nella stessa cartella Development. Poiché la fantasia fa difetto, chiamiamolo articolo.md. A questo punto lanciamo il Terminale, spostiamoci nella cartella Development

$ cd ~/Development

e lanciamo lo script in awk con il comando

$  /usr/bin/awk -f setpostname.awk articolo.md

e voilà, il file articolo.md viene rinominato automaticamente in 2019-02-18-script-per-tutti-i-giorni-entra-in-scena-awk, che è esattamente quello che volevamo. Nota per i più curiosi: dato che awk ha bisogno di sapere sia il nome dello script contenente i comandi che quello del file da elaborare, si usa l'opzione -f per indicare esplicitamente lo script con i comandi.

Perché uso l'intero percorso /usr/bin/awk per richiamare awk? Semplicemente perché voglio essere sicuro di utilizzare l'interprete awk presente di default in macOS e non la versione estesa installata tramite Homebrew, che funziona in modo leggermente diverso e darebbe degli avvertimenti poco incomprensibili, pur riuscendo lo stesso a rinominare correttamente il file.

Conclusioni

Ormai siamo quasi a posto con la rinominazione automatica di un post in Markdown (che poi in effetti è solo una scusa per gettare le basi e per poter affrontare script complessi e più utili). Manca solo un piccolissimo dettaglio, che può far diventare questo script del tutto indistinguibile dai comandi standard del sistema operativo e che sarà l'argomento della prossima puntata.

Bibliografia


  1. Una cosa che io trovo bellissima anche dal punto di vista diciamo così, filosofico, e che mi ricorda i bellissimi articoli di Douglas Hofstadter su Le Scienze sui testi autoreferenziali
Tagged with: , , , , , ,
Pubblicato su programmazione

Script per tutti i giorni: ricapitoliamo


— Foto: Glucksman Library at Limerick su Flickr.

Prima di proseguire con questa serie dedicata alla scrittura di piccoli script in bash e affini, mi sembra utile ricapitolare i concetti principali delle prime tre puntate (qui i link alla prima, seconda e terza puntata).

Case e cartelle

Come tutti i sistemi basati su Unix, anche macOS è progettato per essere usato da più utenti, anche in contemporanea. Nella pratica non è così, nella maggior parte dei casi il Mac è usato da un solo utente e solo di rado vengono attivati degli account per più di tre o quattro utenti, però la funzionalità c’è.

Di conseguenza ciascun utente del Mac dispone di un’area personale dove salvare tutti i documenti, dati e file di configurazione, nettamente separata da quelle degli eventuali altri utenti del sistema. Non a caso quest’area personale è denominata Home, la casa dell’utente.1

Dal punto di vista pratico l’area personale di ciascun utente è costituita da una cartella, rappresentata dall’icona di una casetta e denominata con il nome account (o nome breve), cioè con il nome utilizzato per fare il login sul Mac, che viene assegnato all’utente una volta per tutte al momento della creazione dell’account. All’interno di questa cartella principale ci sono un certo numero di cartelle standard gestite automaticamente dal sistema operativo,2 ma niente impedisce di definire delle ulteriori cartelle personali. Io ad esempio uso la cartella Documenti solo per i file generati automaticamente da certe applicazioni e conservo tutti i miei documenti in alcune cartelle ben definite contenute nella mia Home, dentro le quali ci sono un gran numero di sottocartelle più specifiche.

Una delle cartelle contenute nella mia Home è Development, che uso da sempre per salvare i progetti generici relativi allo sviluppo software (quelli più strettamente collegati alla mia attività lavorativa sono altrove). Proprio per questo ho preferito salvare in questa cartella anche tutti i piccoli programmi proposti nel corso di questa serie, consigliando i lettori di fare altrettanto in modo da seguire più facilmente gli esempi riportati. Chi preferisce usare una cartella diversa dovrà ricordarsi di modificare di conseguenza i percorsi dei comandi.

Già che siamo in tema di cartelle, ribadisco quello che ho scritto nella terza puntata. I termini directory e cartella sono perfettamente equivalenti, io preferisco usare il primo ma so benissimo che nell’uso comune prevale nettamente il secondo, non a caso in tutte le interfacce grafiche l’icona che rappresenta la directory è proprio quella di una cartella di documenti. Ho deciso quindi di uniformarmi all’uso comune e usare il termine “cartella” nel testo discorsivo degli articoli, ma di continuare ad utilizzare “directory” quando il discorso si fa più tecnico, ad esempio ogni volta che tratterò di comandi dei bash e del Terminale.

Il Terminale di macOS

Chi legge i miei post sa che uso moltissimo il Terminale, l’interfaccia a linea di comando di macOS, e lo considero uno strumento insostituibile quando si tratta di eseguire compiti complessi e ripetitivi. Provate ad usare un programma con interfaccia grafica per convertire un centinaio di immagini da un formato ad un altro, sovrapponendo a ciascuna immagine una scritta variabile e poi ditemi.

In macOS il Terminale si trova nella cartella Utility, posta all’interno della cartella Applicazioni, un percorso che possiamo scrivere in modo più compatto come Applicazioni > Utility, dove il simbolo > indica il passaggio da una cartella ad un’altra contenuta al suo interno. Se lo usate spesso e vi secca doverlo andare a cercare ogni volta, aggiungetelo al Dock e vi basterà un click per lanciarlo.

La prima (o la prossima) volta che usate il Terminale fatevi un favore e cambiate un paio di cosette nella sua configurazione standard.

Innanzi tutto lanciate le Preferenze del Terminale, scegliete un profilo più gradevole di quello tutto bianco di base e rendetelo il profilo di default (io preferisco Ocean o Homebrew, ma è una questione di gusti personali). Per farlo, cliccate sull’icona Profili situata nella barra degli strumenti, selezionate dal pannello laterale sinistro il profilo che preferite e infine cliccate sul tasto Default posto proprio in fondo al pannello. Se volete provare i vari profili prima di decidere quale vi piace di più, vi basta fare un doppio click sulle anteprime situate nel pannello laterale.

Chissà perché Apple ha scelto per il Terminale una impostazione di default di appena 80 caratteri per 24 righe (80×24), forse voleva ricordarci come poteva essere lavorare sullo schermo di un Apple II (già in versione “espansa”)! Ma siamo in pieni anni 2000 e un Terminale più grande è decisamente più comodo. Per cui, una volta selezionato il profilo grafico preferito, potete cambiare le dimensioni della finestra del Terminale selezionando il pannello Finestra nell’area centrale delle Preferenze del Terminale e inserendo le dimensioni che preferite, in termini di righe e colonne. Io in genere uso finestre di Terminale da 120 colonne per 40 righe (120×40), forse mi ricorda qualcosa ma comunque mi sembra un buon equilibrio fra ingombro sullo schermo e comodità d’uso.

Se non avete idea di quanto queste dimensioni in righe e colonne si traducano in dimensioni reali sullo schermo, rilanciate il Terminale (per attivare il profilo di default) e allargate la finestra finché non diventa grande abbastanza per i vostri gusti, esattamente come fareste con qualunque altra applicazione per macOS. Per rendere queste dimensioni le nuove impostazioni di default, non dimenticate di cliccare sulla voce Utilizza impostazioni come default del menu Shell (che potrei scrivere anche come Shell > Utilizza impostazioni come default, dove il simbolo > serve in questo caso a separare le voci di menu da selezionare in sequenza).

Il prompt del Terminale

Se l’avete chiuso, lanciate di nuovo il Terminale e guardate con attenzione la finestra che appare. È praticamente vuota, tranne due brevi righe di testo. Se non avete fatto altre modifiche alla configurazione del Terminale rispetto a quelle proposte qui sopra, nella prima riga c’è la data e l’ora correnti con l’indicazione del numero del terminale virtuale correntemente aperto, ttys001, ttys002 e così via. Il Terminale di macOS, infatti, non è altro che un emulatore software dei terminali fisici con i quali, fino agli anni ’80, ci si collegava ai grossi computer delle università o delle aziende mediante un protocollo di comunicazione seriale analogo a quello delle telescriventi. In inglese la telescrivente si chiama Teletype o TTY e l’acronimo è rimasto ancora in uso per indicare appunto i terminali, ormai diventati solo virtuali, dei sistemi Unix come Linux e macOS.

Nella seconda riga invece compare il nome del vostro Mac, quello che avete definito nel pannello Condivisione delle Preferenze di Sistema, seguito dai due punti e dal nome della directory corrente, che in questo momento dovrebbe essere la Home del vostro account, rappresentata dal simbolo tilde, ~ (in macOS la tilde si scrive premendo ALT-5). Subito dopo il nome della directory corrente c’è uno spazio, il vostro nome account e infine il simbolo del dollaro, $.

nome-computer:directory nome-account$ 

Questa riga si chiama il prompt del Terminale, riesce a dare parecchie informazioni utili in modo compatto e, volendo, può essere modificata a piacere (mai capito perché, però se queste cose vi piacciono potete usare questo generatore online).

Quando si descrivono i comandi della shell (che quasi sempre è bash), il prompt del Terminale viene rappresentato spesso con il solo simbolo $, tralasciando tutto quello che c’è prima. Non bisogna mai dimenticare che il $ (o l’intero prompt) serve solo a mettere in evidenza che stiamo usando il Terminale ma non fa parte dei comandi della shell, per cui non dobbiamo mai scriverlo quando interagiamo con il Terminale, magari copiando i comandi dagli articoli di questa serie.

Pillole di bash

E veniamo finalmente ad alcuni fra i comandi principali di bash. Primo fra tutti cd che permette di muoversi fra le directory del disco rigido. Il comando cd deve essere seguito dal percorso completo da seguire per arrivare alla directory desiderata, per cui

$ cd Development

ci fa passare nella cartella Development (supponendo di partire dalla Home), mentre

$ cd Music/iTunes

ci fa andare direttamente nella cartella iTunes contenuta all’interno di Music.

Se ci sentiamo persi, possiamo usare

$ cd

per tornare nella nostra Home, oppure

$ pwd

per stampare nel Terminale il percorso completo della directory in cui ci troviamo. Tutti i percorsi riportati da pwd partono dalla directory /, la radice (o root) del disco rigido,3 per cui se ci troviamo nella Home dell’utente alice, l’esecuzione di pwd restituirà

$ pwd
/Users/alice

dove, come abbiamo già visto, alice è il nome account dell’utente che ha effettuato il login sul Mac. Da notare che in macOS tutte le Home degli utenti si trovano all’interno della directory /Users, a differenza della maggior parte degli altri sistemi operativi basati su Unix (Linux e i vari BSD) che sono più banali ed usano /home.

E per sapere qual’è il nostro nome account? C’è un comando anche per questo,

$ whoami

forse scritto da qualche filosofo esistenzialista.

Con il comando cd si utilizzano spesso delle abbreviazioni molto comode: ~ che indica la nostra directory Home, . che indica la directory corrente (quella riportata da pwd) e .. che invece indica la directory che contiene la directory corrente. Se in questo momento ci troviamo nella directory ~/Music/iTunes

$ cd ..

ci fa fare un passo indietro tornando a ~/Music, mentre

$ cd ~

ci fa tornare nella nostra Home (ma basta anche il solo cd).

Un altro comando fondamentale di bash è echo, che stampa una stringa sul Terminale

$ echo "questa è una stringa"
questa è una stringa

Non è nemmeno necessario racchiudere la stringa fra virgolette, echo stamperà sul Terminale tutto ciò che viene immediatamente dopo il comando, quindi va altrettanto bene scrivere

$ echo questa è una stringa
questa è una stringa

È molto comune utilizzare echo per scrivere direttamente in un file invece che sul Terminale tramite l’operatore di redirezione >

$ echo "questa è una stringa" > file.txt

Se il file file.txt non esiste, echo lo crea da zero e ci scrive dentro la stringa, altrimenti sovrascrive il contenuto precedente di file.txt e lo sostituisce con la nuova stringa. Se vogliamo che il nome del file da creare contenga degli spazi lo dobbiamo racchiudere fra virgolette, non importa se semplici o doppie

$ echo "questa è una stringa" > "file con spazi.txt"

Per scrivere con echo in un file senza perdere il contenuto già esistente, dobbiamo usare l’operatore >> che aggiunge (append) una nuova stringa alla fine del file file.txt

$ echo "questa è una stringa" >> file.txt

Anche in questo caso, se il file file.txt non esiste echo lo crea da zero e ci scrive dentro la stringa.

Gli operatori di redirezione > e >> assomigliano moltissimo ad un altro operatore che abbiamo incontrato più volte nel corso delle puntate precedenti, il | (pipe), che serve a fare in modo che l’output di un comando venga utilizzato come input del comando successivo. Come in questo caso

$ echo "questa è una stringa" | tr "[:lower:]" "[:upper:]"
QUESTA È UNA STRINGA

dove il primo comando echo scrive una stringa e la invia a tr che a sua volta la converte in caratteri maiuscoli e stampa il risultato finale sullo schermo.

Sempre restando in tema di file, ci sono due comandi importantissimi ma piuttosto complicati, chmod e chown, che permettono rispettivamente di cambiare i permessi di lettura (r), scrittura (w) ed esecuzione (x) dei file, e di assegnare la proprietà di un file ad un determinato utente o gruppo di utenti. In questo momento non ha senso entrare nei dettagli dei due comandi, per ora basterà sapere che

$ chmod u+x script.sh

rende lo script script.sh eseguibile da parte dell’utente corrente del Mac, mentre

$ chmod u-x script.sh

rimuove l’autorizzazione precedente. Invece

$ chmod a+x script.sh

rende lo script eseguibile da tutti gli utenti e il suo contrario

$ chmod a-x script.sh

impedisce a tutti gli utenti, quindi anche a noi stessi!, di eseguire lo script in questione.

Per quanto riguarda chown

$ chown alice file.txt

rende file.txt di proprietà dell’utente alice.

I permessi di un file si possono verificare tramite ls, un comando utilizzato di continuo in una qualunque sessione del Terminale per mostrare il contenuto di una directory, cioè tutti i file e le directory (per Unix non c’è differenza) che si trovano all’interno di una directory data. La directory su cui deve operare ls va indicata subito dopo il comando, se non scriviamo niente ls mostra il contenuto della directory corrente.

Il comando ls liscio mostra il contenuto di una directory in forma di tabella, e l’unico modo per distinguere i file dalle directory è tramite l’estensione: normalmente i nomi dei file terminano con una estensione costituita da un punto e da tre lettere mentre le directory non hanno estensione (ma non è detto che sia sempre così). Ad esempio

$ ls ~
Applications  Documentation Library       My Documents  Public        Tmp
Desktop       Documents     Movies        Papers        Research      bin
Development   Downloads     Music         Pictures      Sites

elenca tutte i file e le directory contenuti nella Home del mio Mac (in effetti compaiono solo delle directory). Usato così, ls serve a poco. Molto meglio

$ ls -l

che mostra il contenuto di una directory in forma di lista invece che di tabella, riportando in più una serie di informazioni dettagliate su ciascun file (o directory).

In particolare, la prima colonna contiene una sequenza di 10 simboli — in genere -, d, r, w, x, qualche rara volta anche s o S — che ci dicono se abbiamo a che fare con un file o una directory e quali sono i permessi associati al file stesso (o alla directory).4 Il trattino, -, indica che il permesso corrispondente non è assegnato. I dettagli possono essere letti qui o su una qualsiasi guida introduttiva a bash, come quelle riportate nella Bibliografia qui sotto. A noi basta sapere che la d in prima posizione indica una directory e che se troviamo una x nella quarta, settima o decima posizione significa che il file è eseguibile rispettivamente dall’utente corrente, dagli utenti che fanno parte del suo stesso gruppo o infine da tutti gli utenti del Mac.

Facciamo un esempio pratico: supponiamo di aver creato nella cartella Development lo script script.sh, contenente una serie di comandi bash; appena creato lo script ha i permessi attribuiti di default a un file generico

$ ls -al script.sh 
-rw-r--r--  1 nome-account  staff  0 Jan 25 22:07 script.sh

e poiché non troviamo nessuna x, significa che non può essere eseguito da nessun utente. Per renderlo eseguibile dall’utente attuale del Mac

$ chmod u+x script.sh

come si vede eseguendo di nuovo ls

$ ls -al script.sh 
-rwxr--r--  1 nome-account  staff  0 Jan 25 22:07 script.sh

e notando che il - in quarta posizione è diventato una x. Se invece rendiamo il file eseguibile a tutti gli utenti con

$ chmod a+x script.sh

l’output di ls sarà

$ ls -al script.sh 
-rwxr-xr-x  1 nome-account  staff  0 Jan 25 22:07 script.sh

dove si vede che i trattini in quarta, settima o decima posizione sono diventati delle x. Per riportare tutto alla situazione iniziale

$ chmod a-x script.sh 
$ ls -al script.sh 
-rw-r--r--  1 nome-account  staff  0 Jan 25 22:07 script.sh

Prima di concludere questa lunghissima introduzione a bash, ecco alcuni comandi relativi alla creazione e cancellazione di file e directory. Per creare un file ci sono cento modi diversi, abbiamo già visto come farlo con echo, ma possiamo utilizzare anche il comando touch, che crea un file vuoto da utilizzare in un secondo momento, per cui

$ touch new_file.txt

crea il file vuoto new_file.txt nella directory corrente.

Per rimuovere un file si usa invece rm seguito dal nome del file, quindi

$ rm new_file.txt

cancella il file che abbiamo appena creato con touch.

Analogamente, per creare una directory si usa mkdir (abbreviazione di make directory), per rimuoverla rmdir (abbreviazione di remove directory), seguiti in entrambi i casi dal nome della directory da creare o da rimuovere

$ mkdir nuova_directory
$ rmdir nuova_directory

Anche in questo caso, se il nome della directory da creare (o da rimuovere) contiene degli spazi, deve essere racchiuso fra virgolette semplici o doppie. Per evitare errori che potrebbero essere disastrosi, si può rimuovere una directory solo se è vuota, cioè se non contiene altri file o altre directory.

Credo che per ora possa bastare…

Conclusioni

Questo articolo è cresciuto ben oltre le previsioni iniziali. Purtroppo era necessario farlo, sia per ricapitolare in modo organico le cose dette nelle prime tre puntate, sia per creare un linguaggio di base che permettesse di andare avanti più spediti, evitando di perdersi in troppi dettagli che rallentano e rendono più pesante l’esposizione. Alla prossima puntata con qualche cosa di nuovo e, spero, di interessante!

Bibliografia

I titoli su bash si sprecano. Fra questi vorrei segnalare due guide in italiano e due in inglese. Purtroppo il materiale di qualità in italiano è scarso e le traduzioni dall’inglese sono per forza di cose molto più datate delle versioni originali (lo potete notare chiaramente confrontando le date delle versioni più recenti in italiano e in inglese della guida di Cooper), per cui è quasi sempre preferibile consultare i manuali e i tutorial originali in inglese. Per fortuna l’inglese tecnico è molto comprensibile e non ci vuole molto per riuscire a leggerlo in modo fluido. Certo, se la scuola non facesse di tutto per renderlo odioso, le cose sarebbero più semplici per tutti.


  1. Purtroppo nella versione italiana di macOS è stata tradotta con Inizio, che non rende altrettanto bene l’idea. Io non posso soffrire il termine inizio e userò sempre Home

  2. Fra cui Filmati, Immagini e Musica per i file multimediali, Download per i file scaricati da internet, Documenti per i file personali e Scrivania per i (troppi) file buttati alla rinfusa sul Desktop, cioè sulla scrivania virtuale del Mac. 
  3. O meglio, del file system del disco rigido. Il disco rigido in sé è solo un oggetto hardware che non serve a molto finché non lo si formatta, creando una struttura dati (il file system, appunto) che possa essere utilizzata dal sistema operativo per memorizzare i file. 
  4. In macOS possono anche essere presenti i simboli + o @ nell’undicesima posizione della colonna. 
Tagged with: , , ,
Pubblicato su programmazione
Informativa
Questo sito utilizza cookie di terze parti per inviarti pubblicità e servizi in linea con le tue preferenze. Se vuoi saperne di più o negare il consenso a tutti o ad alcuni cookie, clicca qui. Scorrendo questa pagina, cliccando su un link o su qualunque altro elemento o proseguendo la navigazione in altra maniera, acconsenti all'uso dei cookie.
Follow Melabit on WordPress.com
Categorie
%d blogger hanno fatto clic su Mi Piace per questo: