Archivi Categorie: bash

Bash, quant’è grande, quante cose no so

Ho già confessato più vole che io Julia Evans, b0rk, la lovvo, assay 😍 E se non fossi così timido (e vecchio) una dichiarazione come si usa sarebbe già partita da tempo (ma si usa via Twitter?).

Ho contagiato anche qualcuno dei miei tweeps, recentemente ne parlavo con un nerd, molto più bravo di me, ed ecco un riassunto di quanto ci siamo detti, relativamente a more bash tricks e less.

Cominico con less, per me è più facile. Quando ho iniziato a usare Unix non c’era e l’imprint di more dura tuttora. Ma –me lo dico spesso– devo aggiornarmi. Anche qui ci sono cose che non sapevo, per esempio l’opzione v che ti apre il documento che stai lessando nell’editor definito dalla fariabile d’ambiente $EDITOR: uh! la setto subito, per me export EDITOR=medit verso il fondo di ~/.bashrc.

Il post sui tricks (non so tradurlo in italiano: trucchi? i francesi usano astuces ma astuzie non mi sembra possa funzionare) è ancora più ispirativo.

<(...) confesso che non lo conoscevo; colpa mia, c’è nel manuale Bash Reference Manual, prima o poi lo devo leggere tutto.

3.5.6 Process Substitution

Process substitution is supported on systems that support named pipes (FIFOs) or the /dev/fd method of naming open files. It takes the form of

<(list)

or

>(list)

9.2 Bash History Builtins

Bash provides two builtin commands which manipulate the history list and history file.

fc

fc [-e ename] [-lnr] [first] [last]
fc -s [pat=rep] [command]

Vale quanto detto per $EDITOR ma per adesso mi sembra più semplice richiamare il comando precedente con il tasto freccia-su. E qui si potrebbe inserire tutta la tiritera della history. OT: come la mettiamo con l’apostrofo? la h è ‘taliana o inglisc?

Shellcheck l’avevo già sentita nominare ma mai affrontata. Provandola su qualche scripts ho visto che dovrei aggiungere una spruzzata di virgolette. Da approfondire, c’è il man che mi indica anche il sito (su GitHub, in questi giorni l’unico gioco in città).

I suggerimenti di Julia vanno spesso approfonditi, sono un punto di partenza ma chi ben comincia…

Una nota OT: l’immagine iniziale dei miei post non è mai pertinente; serve solo per Twitter, con un’immagine il post risulta più visibile.

Annunci

Python o Bash per gli scripts?

Se devi ripetere tre (numero che può variare ma comunque non molto più grande di 3) volte la stessa sequenza di comandi conviene fare uno script. Nel mondo Linux (e Unix prima ancora) esistono diversi linguaggi di scripting, si può scegliere volta per volta il più adatto. Un caso simile è capitato proprio ieri, adesso racconto.

Mi serve un contatore per memorizzare successivamente log di elaborazioni. Ecco lo script Bash che ho prodotto:

x-num

#/bin/bash

FileName="$HOME/dep/elab-num"

if [ -e "$FileName" ]; then
  NUM=`cat $FileName`
else
  NUM=0
fi

NUM=$((NUM + 1))
echo $NUM > $FileName

echo $NUM # qui vanno i comandi veri

Il numero dell’ultima chiamata a x-num è memorizzato nel file ~/dep/elab-num. Lo script legge questo numero, lo incrementa di uno, aggiorna il file scrivendo il numero aggiornato e, in questo esempio, scrive sul terminale questo stesso numero. Nella versione vera qui vengono i comandi di elaborazione dei dati. Qualora il file di log non esista il numero dell’elaborazione viene assunto 0; quindi funziona anche in questo caso con indice 1.

Provo a testarlo:

OK, funziona.
Qui devo raccontare una cosa personale, mi è già capitata più volte, continua a capitare, anche ieri… Nello script non si può usare il carattwere ~ per indicare la home, bisogna usare $HOME, cosa che mi dimentico invariabilmente. Adesso che l’ho scritta chissà…

Ieri ero con un amico che è uscito con la solita domanda: “E per Windows come si fa?”

Bella domanda, io uso Python. E questo è l’equivalente Python del precedente

py-num.py

#!/usr/bin/python3

import os

home = os.getenv('HOME')

FileName = os.path.join(home, 'dep/elab-num')

if os.path.exists(FileName):
  with open (FileName, 'r') as f:
    num = int(f.readline())
else:
    num = 0

num += 1
with open (FileName, 'w') as f:
  print(num, file=f)

print(num)

Cancello il file del contatore per essere nelle stesse condizioni di prima ed ecco:

OK. I due scripts fanno esattamente la stessa cosa, possono essere usati in modo intecambiabile (con Linux).

Sono entrambi molto piccoli:

Quale preferire? Se è solo per me io sceglierei la versione Bash, ma sono gusti, l’abitudine (fin dagli anni ’80). La versione Python è però, previa modifica del nome del file, funzionante anche su Windows.

Probabilmente la variabile d’ambiente corrispodente a HOME credo sia HOMEPATH ma chi conosco opera differentemente impostando FileName = "c:/dep/elab-num.txt". Sì meglio specificare l’estensione, anche se di solito non si vede.

“Sai, queste cose si possono fare anche in Basic” (cit.). Certo 😋

🤩

Ricerca con grep, caso con più stringhe sulla stessa linea – 2

Quando ho scritto su grep e la ricerca di più parole o frasi sulla stessa riga ho scritto due cose questionabili; sono stato corretto subito e anche se non sono invidioso non ringrazio il correttore 😡 Non è vero, pesce di metà gennaio 😁 grazie 😁 al giovane collaboratore 💥 PLG 💥 che non blogga e non twitta 😁

La soluzione per lo script bash è quella che ho chiamato “perlosa”, -P, in locale con man grep o qui

-P, –perl-regexp
Interpret PATTERN as a Perl regular expression. This is highly experimental and grep -P may warn of unimplemented features.

Vale per quante siano le espressioni, da una all’infinito (anche se, obiettivamente, dai!).

Ecco lo script, non c’è bisogno di commenti vero? CMQ c’è un accumulatore, PCMD che viene costriuto con gli argomenti, l’ultimo escluso; questo viene poi assemblato con la testa PC e la coda PD che termina con l’ultimo argomento passato.

Per vedere come funziona viene visualizzato –per ora– il comando da passare a eval.

#!/bin/bash

PCMD=""

while [[ $# -gt 1 ]] ; do
  PCMD=$PCMD'(?=.*'$1')'
  shift
done

PC="grep -P '"
PD="' "$1

echo kwindy $PC$PCMD$PD
eval $PC$PCMD$PD

Usando il file gtest ottengo:

gtest

3 4 5
1 4 5 6 2 3
a b c d
1 4 5 6 2 3
2 3 4
6 5 4 2 1 3
xxx
qui non ci sono 1 2 3
qui sì 123654

OK, vista la differenza tra le due richieste?

Ma questa versione ha un grosso bug che lo rende inutilizzabile. Lo so che l’avete già visto ma lo dico lo stesso: interpreta l’ultimo argomento come il nome del file da cercare e solo quello. Quindi non posso dirgli di cercare in più files, eventualmente con l’uso di jollies (? e *).

La modifica richiesta è semplice, introdurre negli argomenti uno di separazione; potrebbe essere -f ma se si volesse cercare proprio quell’espressione? Il più semplice che non dovrebbe generare ambiguità che ho scelto è ^^^.

Lo script diventa quindi:

#!/bin/bash

PCMD=""
while [[ $1 != '^^^' ]] ; do
  PCMD=$PCMD'(?=.*'$1')'
  shift
done

shift # toglie ^^^
PC="grep -P '"
PD="' "$@
eval $PC$PCMD$PD

Posso testarlo per gli scripts in ~/bin che usano awk:

Il carattere # deve essere escapato altrimenti la shell lo interpreta come inizio di commento.

Come verifica posso usare shbp, descritto qui.

Sì, shbp si poteva costruire più semplicemente usando g+. In realtà l’dea di usare grep mi  ci è venuta durante lo sviluppo di shb e shbp 😉

Nota: sì, manca la gestione degli errori; lasciato come esercizio. E nuovamente h/t a PLG 💥

🤩

Cos’è? dov’è?

Un paio di note di programmazione Bash e dintorni; niente di speciale, niente che non si sappia ma c’è un motivo perso: lunedì (ormai non più l’ultimo, ho temporeggiato) me ne serviva un pezzo, ricordavo di averlo fatto ma non riuscivo a trovarlo. Forse se lo metto nel blog… 😋

Quelli come me che installano roba per provarla e non la usano subito e poi —uh! già detto nella frase prima.

Se ci si accorge di usare tre volte (numero che può variare tra i nerds, ma comunque non tanto più grande di tre) un comando composto da più parole probabilmente ti conviene fare uno script. Io lo faccio, di solito.

which
Il primo problema è che la prima riga dello script –la shebang– deve il nome dell’eseguibile, assoluto, completo di tutta la path. Beh, questo è semplice, per esempio:

alias
A volte invece dello script conviene l’alias, per esempio per la REPL di IPython3 io ho:

OK, fin qui niente di nuovo. Ma c’è un utility che può servire, ecco

file
file fa tante cose, vedi man in locale o qui.

Funziona anche quando non penseresti, per esempio

Non è come potrebbe pensare l’utente Windows, non centra l’estensione:

Con ‘opzione -i la risposta è diversa:

E con gli scripts? Eccone uno classico:

hw.sh

#!/bin/bash
echo "Hello World!"

file mi dice

Abilitando lo script il risultato non cambia

Ci siamo quasi, torno a which:

Non lo vede, ma vede altri scripts, per esempio

Ah! funziona solo per le directories elencate nella path.

A ottobre (ahemmm… non l’ultimo) avevo unito which e file, così

tyk

#!/bin/bash

if [[ $# == 0 ]]; then
    exit 2
fi

N=$1
file $(which $N)

OK, ritrovato; ma non è quello che volevo.

alias
Prima accennavo agli aliases, ecco, potrebbe essere più interessante, per esempio

Si può scriptare? uhmmmm…

tyka

#!/bin/bash -i

if [[ $# == 0 ]]; then
    exit 2
fi

AL=$1
r1=$(alias $AL)
r2=$(echo $r1 | sed "s/^.*='//;s/'$//")
which $r2

Notare l’opzione -i nella shebang.

Finora ho trattato script interpretati. Cosa capita se creo l’eseguibile compilando? ecco qualche esempio.

hw.c

#include

void main()
{
    printf("Hello World!\n");
}

hw.nl

(println "Hello World!")
(exit)

hw.rkt

#lang racket/base

(println "Hello World!")

hw.hs

main :: IO ()
main = putStrLn "Hello, World!"

Uh! ‘na cosa che mi ricorda dello scorso millennio: qualcuno degli eseguibili ha informazioni per il debug. Naturalmente la dimensione degli eseguibili ottenuti varia tantissimo

Esiste il comando strip ma serve a poco; ormai lo spazio su disco non è più un problema.

OK, arrivo al punto. Come faccio a cercare eseguibili e scipts con certe caratteristiche?

Distinguere gli script dagli eseguibili è immediato, via file -i

Diventa allora (kwasy) immediato visualizzare la ricerca:

shb
Nota:
corretto in [[ $# -gt 0 ]] (era [[ $# -gt 1 ]])

#!/bin/bash

while [[ $# -gt 0 ]] ; do
  T=$(file -i $1)
  B=$(echo $T | grep "binary")
  if [ ${#B} -gt 0 ]; then
    echo $T     #  binario
  else
    echo $1":" $(head -1 $1) #  testo
  fi
  shift
done

sì ho parecchi comandi che iniziano con _, uno dei quali compilato _u.

Con qualche modifica posso cercare gli script di un determinato linguaggio:

shbp
Corretto l’indice come indicato per shb

#!/bin/bash

P=$1
shift

while [[ $# -gt 0 ]] ; do
  T=$(file -i $1)
  B=$(echo $T | grep "binary")
  if [ ${#B} -eq 0 ]; then
    SB=$(head -1 $1)
    OK=$(echo $SB | grep $P)
    if [ ${#OK} -gt 0 ]; then
      echo $1":" $SB
    fi
  fi
  shift
done

Ed ecco la versione per i compilati:

bex
Corretto l’indice come indicato per shb

#!/bin/bash

while [[ $# -gt 0 ]] ; do
  T=$(file -i $1)
  B=$(echo $T | grep "binary")
  if [ ${#B} -gt 0 ]; then
    echo $1
  fi
  shift
done

OK, mi resta da chmodarne un po’, metterne un po’ in ~/bin e fare pulizia. Prossimamente… Forse… 😋

🤩

Ricerca con grep, caso con più stringhe sulla stessa linea

Capita di dover usare grep in casi in cui produce troppi risultati. Un po’ come quelli cui chiedi un’informazione semplice e la fanno lunga così.

In particolare sono interessato al caso in cui due o più espressioni (anche regexs) siano presenti contemporaneamente sulla stessa riga.

Ken Thompson, il papà di grep (e Unix) rockz! 💥 e ha (giustamente?) pensato che un opzione ad hoc non era necessaria. Cosa che posso verificare subito usando il file esempio.

Questi è il file "esempio" usato come esempio
per la ricerca con grep di più parole o frasi
ma solo quando queste sono sulla stessa riga.

Con °°grep 'ricerca.*parole\|parole.*ricerca' esempio
come si vedrà nello screenshot produce due hits ma
non i seguenti che hanno una sola delle parole per riga:

sì, io uso spesso grep
per cercare parole o frasi
contenute in uno o più file di testo.
E con Linux tutto è testo (kwasy).

E con grep si possono fare tante altre cose.
Questa però, chissà perché, la sanno in pochi.

.* sta per “zero o più caratteri qualsiasi” e | per “or”, dev’essere back-escapata con \. Siccome il risultato è una stringa da-a si rendono necessarie una o più ripetizioni per via dell’ordine con cui le parole o frasi possono comparire.

Ci sono alternative.

Concatenazione via pipe di più grep, utile per ricerche numerose.

funziona ma il colore (dell’opzione --color) viene perso nella pipe.

Oppure con l’opzione perlosa -P

che è OK ma verbosa e si riapre la questione Perl 👌

Io? la prima che ho detto; anzi devo scriptarla 😋 prima o poi lo farò 😋

🤩

em – elementary math

Una storiella  solo per vecchi;   per tutti, dai;  solo per me 😊

Ero con due compagni di sventura a ravanare di cose di ‘puters e salta fuori che si deve valutare una quantità tipo 437 / 36. Io m’impadronisco del portatile, non mio ma già usato, so cosa c’è, e vado:

12 con il resto di 5. Sì, serviva così, roba di interi. A volte la memoria fa strani scherzi, non ho pensato a bc:

OK, ci sarebbero anche altri modi ma credo basti. C. interviene con “con il Vax si calcolavano direttamente queste espressioni”. Al che mi sono sentito che stavo dicendo “anche da noi”. Notare non “con Linux (o Unix) ma ‘da noi'”.

Per fortuna non hanno chiesto come, non lo ricordavo (la memoria…).

Invece è facile, semplicissimo, somma, sottrazione, moltiplicazione, elevazione a potenza, divisione e modulo (resto):

Le espressioni possono essere più complesse, usando se del caso le parentesi

Da ricordarsi che ^ è sinonimo di *.

Si può fare uno script che renda più amichevole l’espressione? Certo!
Però parecchi dei caratteri che vorremmo utilizzare sono metacaratteri, la shell li interpreta e si dovrebbero escapare. Propongo invece di sostituire le parentesi tonde con le quadre, usare x (o X) per la moltiplicazione e ^ per l’elevazione a potenza. Semplicissimo 3 righe (di cui la seconda raccomandata ma non strettamente necessaria), ecco em:

#!/bin/bash
F=$@
echo $(( `echo $F | sed 's/\^/**/g ; s/x/*/gi ; s/\[/(/g ; s/]/)/g'` ))

Sì, per sed parecchi caratteri sono metacaratteri, da escapare.

Resta un mistero: con il Vax, cioè VMS com’era?

🤢

Shell script – i commenti rallentano l’esecuzione?

Ah saperlo! Ho provato a googlare ma niente di che. Ho scoperto cose come Colombo, niente Cina ma la Merica!

Sembra che Python non ne sia influenzato, se non in certi casi, qui.
Inoltre, tornando alla shell: bash è lenta, meglio dash o ksh; ma meglio ancora Perl.
E dash è quella che con ‘buntu si chiama sh, qui e qui.

OK per quanto riguarda la questione in esame niente di meglio che provare, con un test, così alla buona. Tanto gli script sono sempre abbastanza veloci a meno di errori di programmazione, secondo me. E continuerò con bash.

Per i test userò varianti di questo script minimale, c_0:

#!/bin/bash
echo -e "\ntanto per fare qualcosa: "$(( 3 + 4 ))

In questo script inserisco dei commenti. Qualsiasi stringa va bene e allora mi rifugio nei classici. Non so cosa pensate voi della letteratura italiana, per me è sempre stata —ahemmm… non so come dirlo– nel suo complesso. Ma ci sono anche eccezioni, per esempio l’Ariosto con l’Orlando Furioso. Anche Galileo lo cita a volte e allora anch’io.
C’è online, come file di testo, basta scaricarlo:

Il file inizia con un banner, info su Liber-Liber e il Progetto Manuzio, e simili; la prima riga utile è la 159 per cui ecco come procedo per estrarre 10, 100 e 1000 righe.

Il file t10 è questo

inserisco all’inizio di ogni riga # in modo da rendere la riga un commento

Inserisco la shebang

Il comando echo -e "\ntanto per fare qualcosa: "$(( 3 + 4 )) si potrebbe appendere con sed '$ axxxx' t10-1 ma è probabilmente più semplice salvarlo nel file c_ e concatenarlo a t10-1 ottenendo t10.sh:

Lo abilito e lo eseguo usando time per monitorare il tempo richiesto

Similmente creo t100.sh e t1000.sh

OK, i commenti non rallentano 😊
E sì, troppi files temporanei ma era per illustrare il processo passo-passo 😊

Il tempo è talmente breve che è inutile effettuare più esecuzioni; basta questa. Caso risolto, imh0.

:mrgreen:

Fahrenheit to Celsius

Ieri faceva così caldo che non vi dico; proprio da solstizio. In questi casi l’idea di viaggiare con il bus è pessima se capita che i finestrini non si possono aprire e l’impianto di condizionamento non funzioni. A peggiorare il tutto il mio giovane compagno di sventura legge le brekkiniuss sul telefono: in Arizona fa così caldo che gli aerei non possono decollare, 120 gradi Fahrenheit.

Uh! peggio di noi, forse; quanto fa? Velocissimo con una googlata, 48°C.

Ma mi sono preso la rivincita; o almeno ci ho provato. Come fai a passare da una scala all’altra, basta uno script per quella formula semplicissima… 😊

Ora sembra che io sia prevenuto su certe cose come Micro$oft, la scuola, lo zeitgeist tutto ma la soluzione che mi ha prontamente fornito —N.B.: quelli di una certa età deboli di cuore valutino se continuare a leggere, avvisati nèh!— non l’avrei mai immaginata: ha usato un foglio di calcolo, tipo Excel 😯

Io non ero attrezzato al momento ma appena giunti a destinazione l’ho indottrinato, come si deve fare, o si dovrebbe o –almeno– si potrebbe. Basta uno script Bash, con Linux, ovvio.

f2c

#!/bin/bash
if [[ $# -eq 0 ]]; then
    exit 2
fi
    
F=$1
let C="$((($F-32) * 5 / 9))"
echo $F"°F ->" $C"°C"

e per la conversione inversa

c2f

#!/bin/bash
if [[ $# -eq 0 ]]; then
    exit 2
fi
    
C=$1
let F="$(($C * 9 / 5 + 32))"
echo $C"°C ->" $F"°F"

Sì c’è un arrotondamento, si usano gli interi, troncando. Ma volendo essere più precisi ci sono tanti linguaggi –parte lasciata come esercizio 😜 Anche perché qui fa molto caldo 😊

Aggiornamento: l’amico Flavio, the Man from Mars cinguettaGuida per l’Utente del C64 pag. 35. Ai tempi del C64 la conversione °F/°C era già un classico. Il foglio di calcolo è un’esagerazione!
E sì, io sono più vecchio, allora ero alle prese con il Fortran per le stesse cose che adesso vedo e rivedo con Python. Niente C64 ma ho pasticciato con il Vic20 (in Forth).
Tutti d’accordo sull’esagerazione. Non serve Excel, basta VisiCalc 😉

Aggiornamento: lunga conversazione con il giovane amico; ha ragione lui, sono stato parziale, con il telefono mica puoi fare certe cose…
Vero anche che –ma non apriamo un’altra tirata 😊
CMQ (cit.) un modo veloce, disponibile per tutti, al volo:

js-repl
Ah! sembra che la notizia sia confermata.

:mrgreen:

Spazi nei nomi dei files

Anche se non è vero che con Linux si usa sempre il terminale a volte –uh! spesso– è comodo, più semplice e veloce 😎 Poi, certo, quelli abituati alla Finestra Sghemba™ pensano che siamo rimasti agli anni ’80, quando ero ggiovane 😜

Con il terminale capita che i ggiovani (e gli emeriti che se lo sono dimenticato) fanno cose che –anche se si possono fare– poi mandano in errore gli script fatti dai vekki (hey, it’s me!). Per esempio dare ai files nomi contenenti spazi 😡

Ma niente panico (cit.) anche se scripts contenti cp e/o mv non funzionano sono solo one statement away. Ecco come faccio io (csp.sh):

OLDIFS="$IFS"
IFS=""
for f in $@ 
    do
      if [[ -f $f ]]; then
        echo "Processing file $f"
      fi
    done
IFS=$OLDIFS

Da provare, questo è il contenuto della directory

ed ecco:

OK 😁
Ma se non c’è bash, sapete quelli con la finestra di cui si diceva… Uh! on credo che loro siano invogliati a usare queste cose (se non costretti) ma in questo caso si può usare un linguaggio di scripting, ce ne sono tanti, per esempio Python:

#!/usr/bin/python3
import sys, os

for f in sys.argv[1:]:
    if os.path.isfile(f): 
        print("processing file", f)

OK 😁
Ovviamente gli scripts veri saranno resi eseguibili, via chmod (o in un modo più barocco per quelli meno fortunati ma mainstream).

:mrgreen:

Variabili d’ambiente (environment)

Quando si dice la serendipità! 💥
Un meraviglioso post di Julia b0rk Evans mi fornisce lo spunto per un post che diventerà presto (ma non subito) utile con la telenovela su JavaScript.

Mi sa che l’argomento viene visto in modo diverso da Linux e Windows. Comincio con Linux, anche perché è quello che 1) rockz! 🚀 ; e 2) il mio OS 💥.

Ci sono tante variabili predefinite, per esempio USER:

Posso definirne di nuove, per esempio nel terminale:

Così definita è una variabile locale al terminale che l’ha definita. Posso verificarlo con lo script vv.sh

echo $MYVAR

Non viene vista perché è locale al terminale. Per renderla globale (nel senso che sarà precisato tra poco) bisogna espertarla:

Apro uno nuovo terminale (con Ctrl-Alt-T o utilizzando il tasto destro del mouse all’interno del gestore dei files e selezionando “Apri nel terminale”) MYVAR non risulta definita:

Questo perché il nuovo terminale è indipendente da quello in cui la variabile MYVAR è stata definita.

Se invece dal terminale originario apro un terminale figlio (child), così:

MYVAR c’è come previsto. OK, con questo dovrebbe aver chiarito cosa s’intende per locale e globale.
Quando una variabile è davvero importane si può definire in uno dei file di configurazione, nel caso più normale ~/.bashrc.

Tutto questo per poterla usare negli script, ecco per esempio con Python:

import os
print(os.getenv("USER"))
print(os.getenv("MYVAR"))

E, come vedremo prossimamente con NodeJS:

console.log(process.env["USER"]);
console.log(process.env["MYVAR"]);

Windows

Io sono negato con Windows 10 ma sono riuscito a fare questo:

Per aprire il terminale che li si chiama Prompt dei comandi (o qualcosa di simile) ci sono diverse possibilità:

  • tasto Windows + S apre cerca; scrivere cmd + Invio;
  • tasto Windows + X apre il menu; selezionare findestra dei comandi (o qualcosa di simile);
  • tasto Windows + R apre una finestra per ricevere i comandi; scrivere cmd + Invio;

È possibile aprire quante finestre si vuole ma le variabili settate sono visibili solo nella finestra in cui sono state definite. A differenza di Linux non c’è distinzione tra maiuscolo e minuscolo e invece del $ iniziale il nome dev’essere riferito racchiudendolo tra %.
Inoltre l’history dei comandi viene cancellata quando si chiude la finestra.
Siccome non uso mai Windows forse ci sono altre cose che non so; suggerimenti benvenuti 😊

Argomenti sulla linea di comando
Lo vedremo anche questo prossimamente ma rispondo a una richiesta via mail. Come i normali linguaggi anche con NodeJS è possibile passare argomenti allo script che si vuole eseguire; ecco a.js:

args = process.argv
console.log(args.length)
console.log(args)
console.log(args[2])

:mrgreen: