Category Archives: bash

Bash – elencare solo i files

nikon-small-world-head-of-a-skinbow-zebrafish-larvae

È solo un gioco, di quelli senza senso, ma ecco un quiz su Bash o shells affini: qual è l’opzione per elencare solo i files e non le directories?
Uh! ce l’ho qui sulla punta della lingua, ho detto incautamente. Prova -f o -F o -t o -T. No fai ls --help. Azt! no 👿

Poi stante che quando il gioco si fa duro (inizio-cit.) e anch’io ci provo. Googlando un po’ perché mica è facile.

Vero che c’è il comando run-parts che run scripts or programs in a directory.

Sì, ecco la mia interpretazione; apre il file .html precedentemente salvato in locale con Firefox (per esempio quelli di Stack Overflow), funziona anche con nomi con spazi, insomma sarebbe OK.

#!/bin/bash

C=$1
firefox "$(run-parts --list --regex "^$C.*" .)"

Ma l’idea iniziale era di usare ls, comando cui sono affezionato, da trent’anni 😜

Si può fare! (cit.), ecco uff:

#!/bin/bash

C="$1*"
firefox "$(find ./$C -maxdepth 0 -type f)"

sì 😜 ho barato: niente ls ma find –sono affezionato anche a quello 😜

lsf

:mrgreen:

Semplificare l’inserimento di emoji da tastiera

giphotostock

Non ha la pretesa di essere un post serio. E poi non funziona da telefono e allora non interessa the lion share dei possibili utenti; qui dice Cina: China now has 731 million internet users, 95% access from their phones ma ho da poco sbirciato un gruppo di programmatori solo Web, quasi solo JavaScript, principalmente per il mobile.
Anzi i test vengono svolti (quasi) solo su dispositivi Android in verticale. Avevo salvato un link molto divertente (preso da Facebook) ma non riesco a ritrovarlo 😡

emo

Nell’immagine ci sono un po’ di faccine di quelle che se non se ne spruzza un paio per post (per un tweet ne basta una) sembra una cosa non finita. Si possono facilmente selezionare da un ricco catalogo sempre a portata di click ma sapete, io sono vecchio.
Approfittando del fatto che gira e toira (pron. gira e tuira, sarebbe gira e mescola, come quando si fa la polenta) sono sempre le stesse ecco uno script facile-facile e personalizzabile.

#!/bin/bash
function _e {
    case $1 in
        al*) echo -n "👽 " | xclip -f -selection clipboard ;;
        cu*) echo -n "❤️ " | xclip -f -selection clipboard ;;
        ev*) echo -n "👿 " | xclip -f -selection clipboard ;;
        fl*) echo -n "🌺 " | xclip -f -selection clipboard ;;
        fr*) echo -n "🍓 " | xclip -f -selection clipboard ;;
        gr*) echo -n "😄 " | xclip -f -selection clipboard ;;
        id*) echo -n "💡 " | xclip -f -selection clipboard ;;
        li*) echo -n "😜 " | xclip -f -selection clipboard ;;
        lo*) echo -n "😊 " | xclip -f -selection clipboard ;;
        mi*) echo -n "🚀 " | xclip -f -selection clipboard ;;
        oo*) echo -n "😯 " | xclip -f -selection clipboard ;;
        ra*) echo -n "🍇 " | xclip -f -selection clipboard ;;
        ro*) echo -n "🤖 " | xclip -f -selection clipboard ;;
        st*) echo -n "😇 " | xclip -f -selection clipboard ;;    
        tr*) echo -n "😡 " | xclip -f -selection clipboard ;;
        tu*) echo -n "🌷 " | xclip -f -selection clipboard ;;
    esac
}

_e $1
echo

OK, xclip; è tutto lì. Per esempio se digitate:

e0

l’echo finisce nella clipboard; potete verificare con

e1

Ahemmm… scopro adesso che si può semplificare (della serie RTFM 👿)

e2

Quindi lo script consente di inserire nella clipboard di X (quella solita) pronte per essere incollate le faccine elencate dalle sigle mnemoniche (almeno per me; sono pigro e scrivere evil o fragola è troppo impegnativo quando bastano ev e fr) che sono poi quelle (ingrandite) nell’immagine lassù.

Si può usare, lo userò? Chissà… 😜

:mrgreen:

RE – espressioni regolari – un esempio, anzi due; vecchi ma OK

pop1

Il blog di John D. Cook spesso scatena l’ispirazione. Come questo post sulle espressioni regolari, ognuno le fa a modo suo (io per tentativi), queste sono vecchie ma d’autore. Come è vecchio il post (allora il blog si chiamava the Endeavour –il Tentativo– per un motivo che dovete scoprire da soli; e non è quel che pensate) ma rilanciato su Twitter.

The first problem is to produce a list of all English words that contain all five vowels exactly once and in alphabetical order.

Anche se si potrebbe scrivere tutto nel terminale il consiglio è di creare il file alphavowels:

^[^aeiou]*a[^aeiou]*e[^aeiou]*i[^aeiou]*o[^aeiou]*u[^aeiou]*$

e poi lanciare grep. John usa egrep ma –ehi! siamo nel ’17!– l’help di grep dice:

“egrep” significa “grep -E”, “fgrep” significa “grep -F”.
L’invocazione diretta come “egrep” o “fgrep” è deprecata.

E poi il dizionario, almeno per Ubuntu, non si trova dove indicato da John:

j0

Ripasso per me, per nostalgia: i dizionari sono, come Unix prescriveva, file di testo ASCII:

j1

anzi no, ormai Unicode

j2

ma tutto questo è kwasy OT, torno al dunque. Il comando modificato è quindi grep -E -f alphavowels /usr/share/dict/american-english che produce

j3

molte meno di quelle ottenute da John ma la via è quella. Chissà in italiano?

j4

ahemmmm… no, non ne abbiamo 😦

The second problem is to produce a list of all English words of at least six letters with letters appearing in increasing alphabetical order.

The book creates a regular expression named monotonic

^a?b?c?d?e?f?g?h?i?j?k?l?m?n?o?p?q?r?s?t?u?v?w?x?y?z?$

Cerchiamo le parole lunghe almeno 6 caratteri: grep -E -f monotonic /usr/share/dict/american-english | grep '......' e abbiamo

j5

anche qui meno di quelle citate nel post.
Chissà se in italiano…

j6

niente con 6 caratteri, 3 con 5 e 12 con 4.
Ma un momento, manca qualcosa?

j7

Uh! dovrei cambiare nome, quello usato fuori dal Web; ma non risulta neanche il kilo del SI [1]. Continuerò come sempre.
Disclaimer: adoro queste cose ma non è così grave; posso smettere quando voglio; probabilmente; forse… 😳

:mrgreen:



1. kwasy, ricordo che Massimo mi ha già ripreso sull’argomento; forse dovrei scancellare.

Numeri, cambiare base

space_stars_cosmic

Aggiornamento: il post è stato modificato in più punti grazie agli aiuti dei miei amici (sì come Ringo dei Fab4, vedi in fondo) 😀

Un po’ di bash è quello che ci vuole per l’influenza, vero? Almeno ci provo.

Comincio con una cosa semplicissima, trasformare un numero (intero) decimale in esadecimale, ecco 2hex:

#!/bin/bash
echo "obase=16; $1" | bc

Dopo averlo abilitato (con chmod +x 2hex) e averlo spostato in ~/bin ecco:

b0

Questi sono numeri speciali per quelli come me che arrivano dal Fortran 😉 –OK, anche per altri; per quasi tutti.

L’operazione inversa 2dec è un po’ più complessa, bc pretende l’uso del maiuscolo, ma –ke ku c’è tr:

#!/bin/bash
echo "ibase=16;$(echo $1 | tr '[:lower:]' '[:upper:]')" | bc

Aggiormamento #2: ripristinata la versione originaria (questa qui sopra) per ragioni didattiche; la migliore resta ovviamente quella che segue, quella di Flavio.

Aggiornamento: come dice Flavio, the Man from Mars (da seguire qui e qui) si può semplificare, senza scomodare tr:

#!/bin/bash
echo "ibase=16;${1^^}" | bc

b1

A volte serve il binario; e si può partire da un numero decimale o esadecimale. Facciamo che –al solito– il numero è decimale tranne quando inizia con 0x (o 0X). Ecco allora 2bin:

#!/bin/bash
X=$(echo $1 | grep -i x)
case "$X"t in
    t) echo "obase=2; $1" | bc ;;
    *) echo "ibase=16; obase=2; $1" | sed s/0X//I | bc ;;
esac

b2

Adesso b2d, da binario a decimale:

#!/bin/bash
echo "ibase=2; $1" | bc

b3

Aggiornamento: da questo punto in poi il post è nuovo, sostituisce la versione precedente con lamentela per carenze mia (RTFM!). Grazie all’amico f_126_ck.

Da binario a esadecimale (b2x):

#!/bin/bash
echo "obase=16; ibase=2; $1" | bc

b7

Il mio errore era di settare ibase prima di obase. Così facendo avrei dovuto tener conto della base appena immessa per settare obase; invece credevo –erroneamente– che le due variabili fossero sempre da indicare in decimale. Finito il post controllo di non aver scritto qualcosa in proposito nel blog 😳

Ho pensato dapprima di lasciare (indicandola come superata perché errata) la versione precedente ma genera solo confusione, senza aggiungere informazione.

E sì: proprio come si dice qui.

:mrgreen:

Trovare i files cambiati recentemente

knuth-c31b

Non dovrebbe capitare mai ma conviene tener conto di Murphy, non si sa mai.
Non so voi ma a noi (ho un collaboratore che poi vi dico…) a volte capita di salvare un documento e poi non ricordare dov’è.
Recentemente nel Web è comparso questo post 17 Unix tricks for a happy 2017.
C’è un po’ di tutto, qualche dritta è davvero semplice (quelle che già si sanno) ma l’undicesima è sexy. Assay.

11: Finding recently changed files
An alias like the one below will report on the most recently modified files within the current directory.

Ma ha un problema —ioho: solo per la directory (cartella) corrente. Per renderla usabile ha bisogno di qualche hack. Alla fine eco il risultato (ulm):

N=${1:-5}
find $HOME/* -type f -printf '%TY-%Tm-%Td %TT %p\n' | sort -r | head --lines=$N

ulm

Rispetto alla versione pubblicata da Computerworld le variazioni sono la directory che da . diventa $HOME/* e il numero di righe da scrivere.

Ecco, questo è un altro hack che –scommettiamo?– pochi conoscono; per fortuna c’è Stack Overflow: Ternary operator (?:) in Bash.
Ah! mai fermarsi alla prima risposta, nel nostro caso vale la terza, quella di nemesisfixx (rockz!) 😀
Detto in parole comprensibili anche a me: se c’è il primo parametro —$1— a N viene assegnato quel valore; altrimenti N = 5. Provate a scriverla con if… minimo 5 righe 😳

E adesso provate a farla con Windows no dai in questo periodo siamo tutti più buoni (& fluenzati, probabilmente). Uh! 𝕒𝕦𝕘𝕦𝕣𝕚 😀 :mrgreen:

Testo decorato nel terminale – 2

cpp

Continuo da qui, con una versione complementare,  diversa. Cose che capitano quando incontro gente più smart di me, assay 😀
Invece di tutte le combinazioni possibili ne servono solo quelle che si intende usare. E anche la codifica dev’essere più chiara, notare la simmetria dei codici di inizio|fine.

Ci sono 5 codici:
_%e inizia l’evidenziazione
_%E scrive una riga vuota e inizia l’evidenziazione
_%T scrive una riga vuota e un tab e poi inizia l’evidenziazione
z#_ termina l’evidenziazione
Z#_ termina l’evidenziazione e scrive una riga vuota

Insomma ecco tev:

echo -e "$*" |\
    sed s/_%e/\\x1b[31\;47m/g |\
    sed s/_%E/\\n\\n\\x1b[31\;47m/g |\
    sed s/_%T/\\n\\n\\t\\x1b[31\;47m/g |\
    sed s/z%_/\\x1b[m/g |\
    sed s/Z%_/\\x1b[m\\n\\n/g

tev

Basta; argomento chiuso (vero?) 😀

:mrgreen:

Testo decorato nel terminale

ck1

A grande (ahemmmm…) richiesta (come da commenti qui) provo a scrivere sul terminale testo con caratteristiche diverse dal solito, chissà… 😉
In passato me ne sono già occupato, con Python, qui, qui e qui.

L’idea è di usare solo echo e sed. in questo modo:

t-0

Se il comando è lungo ovviamente si può spezzare:

t-1

Adesso è ora di far entrare le sequenze di escape ANSI.
Siccome sono tante procedo un passo per volta, provo…

t-2

I codici sono ostici, posso creare codici mnemonici, ecco i primi 2

V reVerse \x1b[7m
Z reset (Zero) \x1b[m

Ho sostituito \e con \x1b; è il codice di ESC, per qualche modivo si perde con sed.
L’esempio precedente diventa:

t-3

Altri 2 codici:

H bold (Heavy) \x1b[1m
U Underline \x1b[4m
I Italic \x1b[3m

t-4

Notare come i codici si sommino. Pare funzioni. Ce ne sarebbero anche altri, non sempre attivati, omessi.

OK, adesso il colore del testo:

k black \x1b[30m
r red \x1b[31m
g green \x1b[32m
y yellow \x1b[33m
b blue \x1b[34m
m magenta \x1b[35m
c cyan \x1b[36m
w white \x1b[37m

t-5

OK, il bianco è grigino ma va bene così 😀
Cosa succede se due codici colore si sovrappongono?

t-6

ottimo, il nuovo sostituisce il vecchio.

Resta –e temo guai– il colore dello sfondo; i codici sono simili ai precedenti, cambia la serie che va da 40 a 47:

K black \x1b[40m
R red \x1b[41m
G green \x1b[42m
Y yellow \x1b[43m
B blue \x1b[44m
M magenta \x1b[45m
C cyan \x1b[46m
W white \x1b[47m

t-7

Sovrapposizioni:

t-8

Ed è OK anche con testo e sfondo colorati:

t-9

È giunto il momento di fare lo script tdec:

echo -e "$*" |\
    sed s/%H/\\x1b[1m/g  |\
    sed s/%U/\\x1b[4m/g  |\
    sed s/%I/\\x1b[3m/g  |\
    sed s/%k/\\x1b[30m/g |\
    sed s/%r/\\x1b[31m/g |\
    sed s/%g/\\x1b[32m/g |\
    sed s/%y/\\x1b[33m/g |\
    sed s/%b/\\x1b[34m/g |\
    sed s/%m/\\x1b[35m/g |\
    sed s/%c/\\x1b[36m/g |\
    sed s/%w/\\x1b[37m/g |\
    sed s/%K/\\x1b[40m/g |\
    sed s/%R/\\x1b[41m/g |\
    sed s/%G/\\x1b[42m/g |\
    sed s/%Y/\\x1b[43m/g |\
    sed s/%B/\\x1b[44m/g |\
    sed s/%M/\\x1b[45m/g |\
    sed s/%C/\\x1b[46m/g |\
    sed s/%W/\\x1b[47m/g |\
    sed s/%Z/\\x1b[m/g

t-10

Pronto per essere abilitato; notare che l’apice e le virgolette vanno escapati (come gli altri usuali caratteri speciali).

Nota: assemblato alle 15 di giovedì 22; continua a bloccarsi sul salvataggio; copio l’HTML e chissà… 😦
Se continua questa storia passerò al signor Blogspot con un blog tutto nuovo 😀

:mrgreen:

Numeri random e testo in box

btf5

Un po’ di hacking, ogni tanto ci vuole.
Tutto è iniziato con un post di Alessio, the Blaster: Un tiradadi per la shell.
Ha incuriosito un mio contatto. Parliamone 😉
Il codice di Alessio è (abl, corretto per bash):

#!/bin/bash
roll() { echo $[RANDOM % $1 + 1]; }
roll $1

ed è OK 😀 ma poteva essere diverso. Perché creare la funzione roll() che viene usata solo in questo script? In un raptus di semplificazione si arriva a rand, script che potrebbe servire in futuro, da abilitare e mettere in ~/bin.

#!/bin/bash
echo $[RANDOM % $1 + 1]

d0

OK, grazie ad Alessio e S_.
Nota: ho scoperto dopo che esiste un utility chiamata rand (non installata). Tanto funziona quella appena creata.

Non è l’unico script che ci ha incuriosito, via Twitter ecco questo: function box() By @bartonski.
Da provare; questa è la versione originale (b0):

#!/bin/bash
function box() { t="$1xxxx";c=${2:-=}; echo ${t//?/$c}; echo "$c $1 $c"; echo ${t//?/$c}; }

box "$@"

d1

Anche qui si può fare un po di maquillage (b1):

#!/bin/bash

function box() { 
    t="$1xxxx"
    c=${2:-=}
    echo ${t//?/$c}
    echo "$c $1 $c"
    echo ${t//?/$c}
}

box "$@"

Non riporto lo screenshot perché non sono ripetitivo 😉
Inoltre la funzione usata solo qui e allora…

#!/bin/bash

t="$1xxxx"
c=${2:-=}
echo ${t//?/$c}
echo "$c $1 $c"
echo ${t//?/$c}

Continua a funzionare come le precedenti.
Posso ovviamente visualizzare un testo di più parole:

d2

C’è però una cosa che si potrebbe –probabilmente– migliorare. Per il comando echo non servono le virgolette; lo stesso sarebbe bello se anche box
Si può fare! (cit.). Ahemmm… non immediatamente, serve un po’ di googlaggio, inizialmente con braces expansion e infine con parameters expansion. Ecco qui: Learning the shell – Lesson 8: Expansion.
Un minimo di editing ed ecco boxb (la b finale sta per bordo):

#!/bin/bash
par="$*"
S=${par::-1}
t="$*xx"
c=${par: -1}
S=${par::-2}
echo ${t//?/$c}
echo "$c $S $c"
echo ${t//?/$c}

d3

OK 😀 allora…

d4

Dopo qualche prova il carattere da usare come bordo viene individuato e resta quello. Semplifico:

#!/bin/bash

t="$*xxxx"
c=o

echo ${t//?/$c}
echo "$c $* $c"
echo ${t//?/$c}

d5

OK! 😀
Notare come è diventato semplice, ancora più semplice di quello di partenza (Linux is simple… (cit.)).
Ma si userà? Perché nell’hack del sito di Shotts ho scoperto tput:

d6
:mrgreen:

Linux è semplice — ma … (storiella perso)

uis

Questa cit. di Dennis la conoscono tutti (o meglio tutti quelli OK) e forse è un pochino troppo estremista. Non c’è bisogno di essere un genio per apprezzare Linux (il figlio di Unix). Ho una mirabile dimostrazione così breve che può essere contenuta anche in questo post: me. QED.

A dire il vero se torno indietro nei ricordi (no, la macchina del tempo devo ancora finirla) ricordo (appunto) benissimo che UNIX (allora si scriveva così) era universalmente (salvo eccezioni) considerato troppo complesso. Ma è roba dello scorso millennio.

C’è una cosa però che può capitare (spero solo a me) che voglio raccontare perché mi è appena capitata. E per raccontarvela rimando a domani il post che stavo scrivendo su un argomento completamente diverso.

Mentre mi stavo organizzando mi è venuta un’idea di quelle che di solito sono –come dire– ma ogni tanto, chissà… probabilmente… forse…
L’idea è questa: per scrivere il testo di un post creo un file .txt (anche se non uso mai l’estensione, roba da Windoze) con lo stesso nome della directory (non uso mai il nome “cartella”) in cui metto immagini, snippets e quant’altro. È possibile automatizzare la creazione dello stream file? Così:

b0

Evidentemente sì, come da immagine qui sopra, il segreto è racchiuso nello script bash (semplicissimo) bln (da blog name):

#!/bin/bash
N=$(basename "$PWD")
gedit "$N"

Nota: le virgolette e la variabile sono necessarie per gestire il caso di spazi nel nome.

Ebbene sì –confesso– sono tutto arrossito per aver detto una cosa lapalissiana come questa.
Ma c’è un’autogiustificazione, che mi tranquillizza –anzi mica tanto.
Il problema è la memoria. Mia, non quella del ‘puter. Sono partito di qui:

b1

Quasi OK, peccato che il nome della dir sia assoluto, a me serve solo l’ultimo pezzo, quello dopo l’ultimo /.
Fermi lì! (avrei dovuto dirlo anche a me), lo so che ci sono sed, awk e altri tools ancora ma la semplicità di cui parla Ritchie…
Per esempio con Python sarebbe semplicissimo

b2

ma mica tiriamo in ballo Python, vero? tanto vale andare con awk.
Dev’esserci l’equivalente bash, ne sono più che sicuro.
E, pensa te, quello che cercavo era proprio basename!
Ma se devo raccontarla fino in fondo devo confessare che ho googlato

b3

Rinko? 👿
Dai alla fine ce l’ho fatta. Ma metti che fosse tipo che teh boss me lo avesse chiesto e rimanesse lì a guardare il monitor (e me). Secondo me non resisteva per 40 minuti. No 👿

:mrgreen:

Q: Ma davvero hai googlato quella roba lì?
A: Ahemmmm… sai per rendere intrigante il post… 😉

XKCD è la risposta

climagic

Uno dei mystery mysteryousy tuttora senza risposta è il significato di XKCD. Tra le teorie proposte quella che ha più probabilità di risultare un giorno dimostrata è quella che trovate in questo papero cinguettio: The hidden meaning of #XKCD.

È da prendere come dogma (è così, credici!)?
No, nope, come vado a dimostrare [1].

xkcd

Nella sua forma completa lo script è:

printf "%s\n" {A..Z} | nl | grep "[XKCD]" | awk '{sum+=$1} END {print sum}' # The hidden meaning of #XKCD. #AWKtober

Ma si può scomporre; intanto (solo per questo caso, in tutti gli altri servono, sono preziosi) si può togliere il commento finale, il primo # e tutto quello che segue. Però prima ci ricordiamo che #AWKtober (leggetelo come se foste ‘mericani) è un’istituzione, quasi segreta ma si può guardare qui, qui, qui e qui.
Se vi piace Justin Bieber c’è anche questa performance, non assumo responsabilità, nèh,
Twitter poi ha tutta una lista, come si poteva desumere fin da subito dall’hashtag.

OK, vengo allo script, decompongo.
Come primo passo lo riduco così: printf "%s\n" {A..Z} ottenendo

x1

questo è solo l’inizio va fino a Z come richiesto.
Aggiungiamo il secondo pezzo, concatenandolo via pipe: printf "%s\n" {A..Z} | nl e abbiamo

x2

Uh! adesso il terzo blocco, printf "%s\n" {A..Z} | nl | grep "[XKCD]" ed ecco:

x3

Ah! comincia ad essere chiaro basta fare la somma dei records del campo 1, cosa delegata a AWK:printf "%s\n" {A..Z} | nl | grep "[XKCD]" | awk '{sum+=$1} END {print sum}'

x4

OK! possiamo fare anche la verifica, usando uno tra i millantamila linguaggi di programmazione; che ne dite di usare il migliore, così:

x5

OK! adesso fatelo con Windows [2] 😀

Io posso smettere quando voglio. Probabilmente… forse…


[1] con la collaborazione di Sole (yesss! esistono anche ings prestate all’informatica).
[2] Sole si dissocia, netti che teh Boss legge il post…

:mrgreen: