Buongiorno a tutti e benvenuti ad
un altro post del mio blog : "lo Scriptomane".
Oggi parleremo di come ottenere,
con uno script, un funzionamento molto simile a quello del comando tail di
Linux/Unix anche sui nostri amati host windows.
Lo script: TAIL.BAT
@ECHO OFF
REM tail.bat
REM Implementazione di un comando TAIL in windows batch di Diego Castelli.
Setlocal EnableDelayedExpansion
for /f "usebackq delims=: tokens=1,2,*" %%f in (`find /c /v "" %1 ^|FINDSTR /R /C:":[\s]*[0-9]*"`) do (
REM echo f: %%f g: %%g h: %%h
set /A fileLines=%%g
set /A Lns=%2
set /A Lns2Skip=!fileLines!-!Lns!
more "%1" +!Lns2Skip!
REM for /f "usebackq skip=%Lns2Skip% delims=" %%d in (%1) do echo %%d
)
Devo dire che, prima di esplorare a fondo le caratteristiche del comando FOR di batch, tail era uno strumento che sognavo di usare nei miei scripts… mi faceva una grande invidia quando lo utilizzavo dalla riga di comando o in uno script bash.
Piano piano, vedendo le opzioni di FOR, si è insinuata l’idea
di poterlo realizzare anche in batch in modo semplice, per espandere le capacità
degli script e raggiungere nuovi livelli di automazione…
Ecco quindi la spiegazione, step by step di come si comporta
lo script:
prepariamo l’ambiente
Salterò “i convenevoli” e non parlerò di echo off e setLocal
EnableDelayedExpansion. Se volete approfondire vi invito a leggere un altro
post del mio blog:
il mitico FOR
Qui sotto copio e incollo le spiegazioni dell’help del
comando for, per dettagliare cosa fa ogni cosa:
con l’opzione /f "usebackq delims=: tokens=1,2,*"
andiamo a dire a FOR:
/f : usa le opzioni estese che verranno specificate tra
virgolette
Usebackq: Specifica che sono attive le nuove semantiche, in
cui le stringhe con apici inversi vengono eseguite come comandi e le stringhe
con virgolette singole sono comandi con stringhe letterali in cui è possibile
utilizzare le virgolette doppie per specificare i nomi di file in un gruppo di
file.
Delims=: : Specifica un insieme di delimitatori. Tale insieme
sostituisce i delimitatori predefiniti (spazi e tabulazioni).
In pratica, qui stiamo dicendo che le “colonne” del nostro output sono separate
dai due punti e che FOR deve incrementare di una lettera dell’alfabeto (partendo
da quella specificata poi nella variabile) ogni volta che passa ad analizzare
la “colonna successiva”
Tokens=1,2,* : Specifica i token da passare, per ogni riga,
al corpo del blocco FOR a ogni iterazione. Determina l'allocazione di nomi di
variabile aggiuntivi. L'espressione m-n indica l'intervallo dei token compresi
tra la posizione m e la posizione n. Se l'ultimo carattere della stringa
specificata dopo tokens= è un asterisco, verrà allocata una variabile
aggiuntiva in cui sarà inserito il testo rimanente sulla riga dopo l'ultimo
token analizzato.
In sostanza, stiamo dicendo che ci interessano la prima “colonna”,
la seconda e poi tutto quello che viene dopo, a prescindere da quanti delimitatori
si incontrano da lì in poi.
Ad ogni token viene associata una variabile che parte dalla lettera
dell’alfabeto scelta poi (%%f ), quindi le
variabili che ci aspettiamo popolate durante il ciclo saranno %%f, %%g, %%h
in (`find /c /v "" %1 ^|FINDSTR /R
/C:":[\s]*[0-9]*"`) do ( : utilizziamo l’output del comando tra le
back-quotes (a proposito: ALT+96 sul tastierino numerico, per farle) e lo
analizziamo riga per riga.
Ora, il comando principale è find /c /v "" %1,
ossia, trova il carattere NESSUNO e conta le righe che NON lo contengono (/v)
all’interno del file %1, che è il primo parametro che passiamo al nostro batch
Il comando secondario (a cui passiamo l’output del principale
mediante una PIPE, qui correttamente preceduta dal carattere di escape), lo uso
per filtrare l’output, perché il comando principale ha un output di 3 righe: la
prima e l’ultima sono vuote, quindi se non facciamo niente ci troveremo le
variabili VUOTE, perché l’ultima esecuzione del ciclo sarebbe su una riga vuota
e quindi…
Ma per far capire meglio, eseguiamo in una shell i comandi
ad uno ad uno.
Ci alleneremo con il file c:\windows\system32\DISMLog.log
che è il log dello strumento di gestione e manutenzione immagini di windows (è
un log di sistema, in sostanza, senza che mi dilunghi…).
FIGURA1 |
Come vedete, il comando conta quante righe NON contengono un
carattere NULLO (quindi conta tutte le righe del file), ma vedete che l’output
è di 3 righe: la prima e l’ultima sono vuote. A noi interessa solo quella
centrale
Ecco quindi che ci viene in aiuto la PIPE ad un altro FIND:
FINDSTR, che è in grado di analizzare l’output anche con le regular expressions.
FIGURA2 |
Come vedete in figura 2 l’output è arrivato pulito… possiamo
quindi analizzarlo con il FOR senza temere errori.
Settiamo le variabili
Con le righe
set /A fileLines=%%g
set /A Lns=%2
set /A Lns2Skip=!fileLines!-!Lns!
Definiamo le variabili :
fileLines = numero totale di righe
Lns = numero di righe da mostrare dalla fine del file
Lns2Skip = quindi, il numero da saltare (totale – righe da
mostrare)
More
A questo punto usiamo il comando more, passando il nome del
file da analizzare e il totale delle righe da saltare, preceduto dal + (è un
parametro speciale del comando more).
More mostra il file in modalità particolare: ossia mostra
una schermata alla volta, lasciando all’utente la possibilità di proseguire
(con la barra spaziatrice o con l’invio, sperimentate! – tasto q per “quit”)
FIGURA3 |
… ed eccoci arrivati alla fine dell’articolo. Per usare il
nostro simpatico tail, ci basterà richiamarlo dall’interno dei nostri script o
direttamente dal prompt e passare, come primo parametro il nome file e come secondo
il numero di righe da mostrare dalla fine.
Tutto qui.
Qui sotto in figura 4 vi mostro le ultime 12 righe del file di log.
FIGURA4 |
Che dire... spero di aver stuzzicato la vostra fantasia e...
Happy Scripting a tutti!
Nessun commento:
Posta un commento
I commenti sono soggetti a moderazione, prima di essere pubblicati.
Qualsiasi contenuto illecito, immorale o che io ritenga (arbitrariamente) offensivo od inappropriato, verrà cancellato.