martedì 26 luglio 2011

Riorganizzare o rinominare i files immagine e MP3 con i dati EXIF e ID3 (e, ovviamente, leggere i dati EXIF e ID3) - Parte 1 - Lo Scriptomane - livello MEDIO

Qualche giorno fa, mi è stata fatta un'obiezione (peraltro legittima) da un amico: ma che c@#[o mi metti in copia conoscenza dei tuoi post sul blog, che io sono un grafico (per farla breve) ... posso apprezzare, capire il concetto, ma....

Caro Tiz, hai ragione!

Per questo ho deciso di pubblicare qualche script che abbia utilità comune, in modo da interessare anche chi non fa il sistemista di mestiere... .... e siccome ho tanti amici grafici e/o appassionati di fotografia....

Oggi parliamo di come leggere i dati EXIF delle immagini in una cartella e spostarle / rinominarle in base a questi dati.

I dati EXIF sono messi nelle proprietà delle immagini da TUTTE le fotocamere digitali oggi in commercio ed includono dati MOLTO interessanti, come il tempo di posa, l'apertura del diaframma e addirittura possono contenere  la GEOLOCALIZZAZIONE dell'immagine, se la fotocamera o il telefono sono stati correttamente impostati.

Per visualizzarli in windows potete cliccare con il destro su una immagine e scegliere proprietà. Nella scheda Dettagli troverete le informazioni di cui vi ho parlato.

Pubblicherò qui TRE script (nella parte 1, parte 2 e parte 3 di questo multi-articolo succulento): uno che ottiene tutte le info di un file che abbiano qualche dato dalla "info 0" alla "info 500"***, uno che sposta le immagini in cartelle in base alla proprietà "DATA DI ESPOSIZIONE", l'ultimo le rinomina, includendo i dati di "tempo di esposizione" ed "apertura del diaframma". Sentitevi liberi di chiedere per qualsiasi modifica che vi è necessaria per le vostre esigenze....


*** lo script può facilmente essere reiterato per tutti i files di una cartella con un semplice batch con il comando FOR, che includerò qui.

lunedì 18 luglio 2011

VBScript: come tenere traccia dello spazio dischi su Windows Server 2003, 2008 e 2008 R2 - Lo Scriptomane - livello BASE

A volte ci si trova a chiedersi perchè un processo fallisca o a quale punto fallisca (esempio tipico: un piano di manutenzione di SQL server) oppure, per qualsiasi altro motivo, qual'è il momento esatto in cui si riempie un disco.

Altre volte, si vuole semplicemente monitorare la situazione dei dischi, tenendone traccia. Ad esempio quando si vuole calcolare la business growth per la stima della scalabilità del sistema di file server/s.

Per tutte queste ed altre necessità, è sufficiente un piccolo script, schedulato ad intervalli più o meno vicini, che permette di avere un log con data ed ora di ciascuna rilevazione.

In calce trovate lo script completo, basta copiarlo ed incollarlo in file di testo, salvandolo come .vbs



Ma vediamone insieme ciascun pezzo:

Option Explicit
Dim iSpc, strComputer, objWMIService
Dim fso, fsHandle, MyShell,LogFileName, colItems, objItem


DICHIARIAMO LA MODALITA' DI ESECUZIONE "STILE VB6""" " E LE VARIABILI INIZIALI


Set MyShell = CreateObject("Wscript.Shell")

CREIAMO UN OGGETTO SHELL (la tanto amata shell)

Set fso = Wscript.CreateObject("Scripting.FilesystemObject")

CREIAMO UN OGGETTO FILESYSTEM: CI SERVIRA' PER CREARE E SCRIVERE IL FILE DI LOG

LogFileName= MyShell.SpecialFolders("Desktop") & "\FreeSpace.txt"
set fsHandle = fso.OpenTextFile (LogFileName,8,True)

DEFINIAMO IL NOME DEL LOG, CHE VERRA' SALVATO SUL DESKTOP PER COMODITA'

strComputer = "."

IL COMPUTER E' IL LOCALE (.)
 
Set objWMIService = GetObject _
( "winmgmts:\\" & strComputer & "\root\cimv2")
Set colItems = objWMIService.ExecQuery _
("Select * From Win32_LogicalDisk Where DriveType = 3")

Creiamo le collections con le query WMI, ottenendo tanti oggetti disco quanti sono i dischi LOCALI (DriveType=3).

For Each objItem in colItems
 
iSpc = cDbl(iSpc) + cDbl(objItem.FreeSpace)
iSpc= iSpc/1024
iSpc= iSpc/1024
iSpc= iSpc/1024
iSpc= FormatNumber(iSpc,1)
fsHandle.Writeline Now & " -- " & objItem.DeviceID & " -- " & iSpc & " GB Spazio Libero"
 
Next

PER CIASCUNA VOCE:
  1. convertiamo il valore della proprietà FreeSpace in una variabile DOUBLE con cDbl
  2. lo dividiamo 3 volte per 1024 (1 GB = 1024 MB, 1 MB = 1024KB, 1KB = 1024 Bytes) perchè il valore fornito è in Bytes.
  3.  Lo formattiamo come intero
  4. lo scriviamo in una nuova linea con il valore della data e ora attuali (Now), la lettera (DeviceID) e lo spazio libero calcolato in GB.



fsHandle.Writeblanklines 1
fsHandle.close
set MyShell = Nothing
set fso = Nothing

Scriviamo una riga bianca, chiudiamo il file ed annulliamo gli oggetti, per liberare la memoria.



Ed eccolo qui, pronto per Voi:

################# INIZIO ####################

Option Explicit
Dim iSpc, strComputer, objWMIService
Dim fso, fsHandle, MyShell,LogFileName, colItems, objItem
Set MyShell = CreateObject("Wscript.Shell")
Set fso = Wscript.CreateObject("Scripting.FilesystemObject")
LogFileName= MyShell.SpecialFolders("Desktop") & "\FreeSpace.txt"
set fsHandle = fso.OpenTextFile (LogFileName,8,True)

strComputer = "."

Set objWMIService = GetObject _
( "winmgmts:\\" & strComputer & "\root\cimv2")
Set colItems = objWMIService.ExecQuery _
("Select * From Win32_LogicalDisk Where DriveType = 3")

For Each objItem in colItems
'recupera le info e converti da uint64
iSpc = cDbl(iSpc) + cDbl(objItem.FreeSpace)
iSpc= iSpc/1024
iSpc= iSpc/1024
iSpc= iSpc/1024
iSpc= FormatNumber(iSpc,1)
fsHandle.Writeline Now & " -- " & objItem.DeviceID & " -- " & iSpc & " GB Spazio Libero"
Next

fsHandle.Writeblanklines 1
fsHandle.close
set MyShell = Nothing
set fso = Nothing


############FINE ###############

giovedì 14 luglio 2011

5up3rH4ck3r13n4! - Lo Scriptomane - livello AVANZATO

5up3rH4ck3r13n4!
...
...
Ho Vinto!
Bene signori e signore, ho vinto ancora.

Un po’ di storia:
Microsoft Exchange Server è lo strumento di messaging e collaborazione che rappresenta lo stato dell’ arte per quanto riguarda posta elettronica, calendario, documentazione, to-do e contatti .
In azienda siamo i fortunati possessori di un’edizione 2003 standard SP2. Edizione che fu molto fortunata per Microsoft, sia per Exchange che per Windows Server. Infatti introduceva una vasta serie di nuove possibilità diminuendo la complessità del management e presentando console molto più unificate.

Il Caso:
Mi è stato richiesto di creare un sistema automatizzato per la prenotazione delle sale riunione….
Detto fatto! Creo degli utenti – risorsa, con i nomi delle sale riunione, e li configuro come da documentazione Microsoft in merito.
Quando un utente deve prenotare una sala riunione, non deve fare altro che “invitarla”, ma non come partecipante, come “risorsa” appunto.
L’account delle sale riunione accetterà automaticamente appuntamenti che non siano in conflitto con altri, diversamente li rifiuterà.
Inoltre è possibile vedere la disponibilità della sala in modalità pianificazione



senza per questo dover avere accesso ai dettagli degli eventi altrui. Se non si è partecipanti invitati od organizzatori di un evento, si vedrà soltanto la “barretta” che indica che sarà in corso una riunione, in quel luogo ed in quel momento.
Caratteristica eccezionale di Exchange, vero? Ma….

Il Problema:
dopo pochissimi giorni dalla loro creazione le sale riunione hanno smesso di aggiornare le informazioni di disponibilità (free/busy informations), che in exchange 2003 vengono stoccate in una public folder (una cartella condivisa) sotto forma di “messaggio speciale”.
Quindi le persone non potevano verificare la disponibilità della sala prima della pianificazione ed inoltre la sala accettava RICHIESTE IN CONFLITTO!

Il tutto veniva visualizzato come in figura:

Come potete notare, la sala riunione convocata NON MOSTRA le informazioni di disponibilità. Quando la sala si trova in questo stato, è possibile anche che riunioni vengano prenotate contemporaneamente da più persone nella stessa sala... Con risultato catastrofico...

Dopo varie indagini (e grazie anche alle risposte sul forum di Microsoft), sono giunto alla seguente conclusione:  non vengono aggiornate perché l’utente della sala riunione non effettua modifiche DI PERSONA al calendario.
Voi direte: ma come?!?!?! Ma se è appositamente previsto che sia un utente NON usato da nessuno!
Ebbene è così.


La paventata soluzione:
Microsoft ha rilasciato una "mezza soluzione" a questo link:
http://support.microsoft.com/kb/294282/en-us

Secondo me è una "mezza soluzione" perchè richiedono l'apertura di una chiamata a pagamento (partono da 300 euro circa) per inviare le utility....

Queste utility, come dice anche la descrizione che trovate nella KB di Microsoft (link sopra), non fanno altro che accedere al calendario dell'utente ed inserire degli appuntamenti fittizi.
Una volta capito di cosa si trattava ho deciso di farmelo da me. (chi fa da se fa per tre).



La vera soluzione: 
REQUISITI:

Vi basta avere un PC o un server sempre accesi, durante l'orario di lavoro, con un utente che abbia accesso completo alle cassette delle sale riunioni ed abbia una qualsiasi versione di outlook dal 2003 al 2010...
Impostate diversi profili per l'accesso alle diverse cassette postali (anche se il profilo di default può restare immutato, quindi questi risultano "nascosti") et voilà.
Nel mio caso poteva andare bene il PC di un responsabile del personale o della segreteria generale, ma ho outlook anche su un server, quindi...
Eccolo qui, il mio script, nudo e libero, per tutti voi:

########### file freeBusyUpdate.vbs ###############
Sub CreaAppto(strProfileName)
 Dim objOL
 Dim objAppt
 Const olAppointmentItem = 1
 Const olMeeting = 1
 Const olFree = 0

Set objOL = CreateObject("Outlook.Application")
Set objNamespace = objOL.GetNamespace("MAPI")
    objNamespace.Logon strProfileName,, False, True
 Set objAppt = objOL.CreateItem(olAppointmentItem)

objAppt.Subject = "Appuntamento di sistema by Diego"
objAppt.Start = Date + 1 + TimeValue("19:30:00")'domani alle 19:30
 objAppt.Duration = 1
 objAppt.Location = "DoveVuoi"
 objAppt.Body = "Questo appuntamento di un minuto creato alle 19:30, serve per aggiornare automaticamente le informazioni sulla disponibilità dei profili delle sale riunioni..."
 objAppt.ReminderMinutesBeforeStart = 1
 objAppt.BusyStatus = olFree
 objAppt.Save()
 WScript.Sleep 1000 'attendi un secondo
 objAppt.Delete() 'cancellalo
 Set objAppt = Nothing
 Set objOL = Nothing
 End Sub
 CreaAppto("salaRiunione1")
 CreaAppto("salaRiunione2")
 CreaAppto("salaRiunione3")
 CreaAppto("salaRiunione4")

########### FINE file freeBusyUpdate.vbs ###############


Ma commentiamolo insieme…
Sub CreaAppto(strProfileName)
 Dim objOL
 Dim objAppt
 Const olAppointmentItem = 1
 Const olMeeting = 1
 Const olFree = 0
^ qui dichiaro la funzione (Sub) che riceve un parametro stringa “strProfileName” che corrisponde al nome del profilo di outlook configurato con l’utenza della sala riunione corrispondente.

Set objOL = CreateObject("Outlook.Application")
Set objNamespace = objOL.GetNamespace("MAPI")
    objNamespace.Logon strProfileName,, False, True
^qui creo l’oggetto “outlook.Application” (in pratica apro outlook), Imposto la sessione MAPI (protocollo di collegamento tra outlook ed exchange), Mi loggo al profilo selezionato.



Set objAppt = objOL.CreateItem(olAppointmentItem)
objAppt.Subject = "Appuntamento di sistema by Diego"
objAppt.Start = Date + 1 + TimeValue("19:30:00")'domani alle 19:30
 objAppt.Duration = 1
 objAppt.Location = "DoveVuoi"
 objAppt.Body = "Questo appuntamento di un minuto creato alle 19:30, serve per aggiornare automaticamente le informazioni sulla disponibilità dei profili delle sale riunioni..."
 objAppt.ReminderMinutesBeforeStart = 1
 objAppt.BusyStatus = olFree
 objAppt.Save()
^ qui creo l’appuntamento, imposto l’oggetto, lo start time a Date+1 (cioè domani ) alle 19:30, imposto la durata a 1 minuto, metto la location, scrivo del testo nel corpo dell’evento, imposto il reminder ad un minuto prima di iniziare, metto che la sala deve essere vista come disponibile (olFree) durante il periodo e infine salvo l’evento.
WScript.Sleep 1000 'attendi un secondo
 objAppt.Delete() 'cancellalo
 Set objAppt = Nothing
 Set objOL = Nothing
 End Sub
 CreaAppto("salaRiunione1")
 CreaAppto("salaRiunione2")
 CreaAppto("salaRiunione3")
 CreaAppto("salaRiunione4")
^qui attendo un secondo (1000 millisec), cancello l’evento e chiudo le connessioni ed outlook. Poi chiudo la funzione.
Infine richiamo la funzione quattro volte, una per ogni cassetta postale risorsa, indicando il nome di ciascun profilo di outlook a cui ho associato i rispettivi account.


Ed ecco fatto, schedulatelo ogni due ore nell'orario di lavoro e non avrete più problemi!
Implementato da due settimane e non ho più visto l'errore, controllato ogni giorno!

Alla faccia degli script supersegreti del c@#[0. 
Yeah.


P.S. se vi capita di farci dei soldini o di risolvere problemi, magari dite che "avete un amico fikissimo, che scrive un blog fikissimo"...


Ciao!

lunedì 9 maggio 2011

Exchange 2007: come usare la whitelist per nomi di dominio. - Lo Scriptomane - livello MEDIO

Non troppo recentemente ho sviluppato uno script per gestire le whitelist entries del Filtro Contenuti di Microsoft Exchange 2007, con la powershell di Exchange (Exchange Management Shell).


  -  per chi non sapesse di che cosa diamine parlo : http://technet.microsoft.com/en-us/library/bb124739%28EXCHG.80%29.aspx   -


In questa versione del famoso server di posta MS, questo è l'UNICO modo di farlo e, tra le altre cose, non si può che fare con uno script, se si vuole mantenere le entry precedenti. Questo perchè non esiste alcuna funzione "Add" per la proprietà "BypassedSenderDomains" dell'oggetto "contentFilterConfig".

Vorrei dare il mio contributo a rendere più facili le simpatiche pratiche di gestione per quei sistemisti che non sono scriptomani come me, ma si trovano a dover fronteggiare sempre di più la tendenza (che peraltro condivido pienamente) di Microsoft a fornire sempre più possibilità solamente da riga di comando/script, con quel fantastico strumento che è PowerShell.

Usando lo script (che trovate in calce nella sua versione completa), vi viene semplicemente richiesto il nome di un dominio da white-listare e questo viene fatto. Immediatamente.


Ma procediamo al commento delle singole righe dello script:




 [void][System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic')

Questa riga richiama la gestibilità degli oggetti VisualBasic nella Powershell.

$a = [Microsoft.VisualBasic.Interaction]::InputBox("inserire il dominio da mettere in white-list", "Whitelist Dominio", "")

Creiamo una istanza  della InputBox (la finestrella che ci chiederà il nome del dominio da mettere in white-list) e valorizziamo la variabile $a con quanto immesso dall'utente.
 
$cf = get-contentFilterConfig

Creiamo una istanza dell'oggetto contentFilterConfig


$cf.BypassedSenderDomains += $a
impostiamo la sua proprietà che ci interessa (BypassedSenderDomains) AGGIUNGENDO (+=) il dominio appena immesso.ATTENZIONE: stiamo modificando una istanza dell'oggetto e non applicando la configurazione direttamente.

$cf | set-ContentFilterConfig

Qui facciamo in modo che le modifiche all'istanza vengano applicate alla configurazione in essere di Exchange 2007, usando il comando set-ContentFilterConfig e passandogli l'oggetto $cf nella PIPE .

echo $cf.BypassedSenderDomains

Mostriamo l'elenco aggiornato dei domini in white-list.








############### Script completo ###############################
[void][System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') 
 
$a = [Microsoft.VisualBasic.Interaction]::InputBox("inserire il dominio da mettere in white-list", "Whitelist Dominio", "") 
 
#$a=read-host "inserire il dominio da mettere in white-list"

$cf = get-contentFilterConfig
$cf.BypassedSenderDomains += $a
$cf | set-ContentFilterConfig
echo $cf.BypassedSenderDomains


giovedì 10 febbraio 2011

Come prendere l'output di un comando e impostarlo come variabile. - Lo Scriptomane - livello MEDIO

Buongiorno, ecco il secondo articolo di questo mio piccolo spazio dedicato allo scripting che promette di essere una guida per chi vuole dedicarsi ad un approccio innovativo per la gestione delle operazioni di amministrazione di computer, reti e quant'altro.

Al contrario del mio "cugino" americano: "the Scripting Guy", che ammiro molto e che è stato per me molte volte una guida, io cerco di non scomodare il signor VBScript quando non è proprio necessario.

Windows ha un cuore di scripting dalle potenzialità spesso inespresse / non documentate: il batch.

Oggi vedremo un argomento controverso a cui viene spesso data la risposta "non si può":
Come prendere l'output di un comando e impostarlo come variabile.

in batch si usa SET per impostare variabili ambiente (usate il comando SET senza parametri per visualizzare una lista completa di variabili ambiente presenti nel vostro PC, oppure "SET a" per vedere solo quelle che iniziano con a e via dicendo...).

il comando SET, come tutti gli altri comandi, può essere messo in un ciclo del comando FOR e il comando FOR è un tipo in gamba ad analizzare l’output dei comandi. Basta lanciare il comando che vogliamo analizzare dalle sue “parentesi”. Oggi vedremo anche un altro aspetto che di solito spinge gli scripters a redirigere l’output di comandi prima verso file di testo: il PIPING* all’interno del FOR mediante l’uso dei caratteri di ESCAPE*

Ma vediamo subito nella pratica.
Una delle operazioni più comuni che vorrebbero ottenere i sistemisti da un linguaggio di scripting è ottenere l’indirizzo IP del computer in uso, la sua netmask e il gateway predefinito. OK, mettete quanto segue in un file di batch:

@echo off
setlocal EnableDelayedExpansion
SET i=0
FOR /F "usebackq delims=: tokens=1,2,*" %%a IN (`IPCONFIG ^| FINDSTR /I "Indirizzo Subnet Gateway"`) DO (
set var!i!=%%b
SET /A i=!i!+1
)
echo var0: !var0!
echo var1: !var1!
echo var2: !var2!
pause
in var0 c'è l'IP, in var1 c'è la MASK, in var2 il gateway.

A questo punto urge una spiegazione, line by line, command by command:

@echo OFF -> evita che nell'output VISIVO, si vedano i comandi lanciati.

setlocal EnableDelayedExpansion -> Abilita l'espansione delle variabili all'interno del ciclo FOR (altrimenti sarebbero tutte VAR0 o VAR2 che si sovrascrivono, perchè le operazioni sulle variabili vengono eseguite tutte prima del ciclo FOR effettivo... un guazzabuglio: fidatevi di me). Quando si abilita questa caratteristica, le variabili vanno richiamate con !nomeVar! e non più con %nomeVar%. IMPORTANTE!

SET i=0 -> imposta la variabile %i% uguale a 0, ci servirà come "pezzo" del nome variabile.

... qui procedo più con calma
FOR /F "usebackq delims=: tokens=1,2,*" %%a ... -> qui diciamo al FOR di usare le estensioni dei comandi "usebackq", di analizzare l'input trovando i separatori ":" e di usare il primo valore prima di ":" come prima variabile, il secondo valore dopo i ":" come seconda (%%b, perchè va in ordine alfabetico) e, se anche trovasse un terzo ":" e un quarto ":", tutto ciò che viene dopo il terzo ":" come terza variabile.





... IN (`IPCONFIG ^| FINDSTR /I "Indirizzo Subnet Gateway"`) DO ( -> qui dico al comando FOR di analizzare riga per riga dell'output del comando incluso in apici inversi " ` " (si ottengono con il codice ASCII 96, quindi: tengo premuto ALT e scrivendo 96, poi rilascio ALT e "appare magicamente").
Il comando che inserisco dovrebbe essere IPCONFIG | FINDSTR /I "Indirizzo Subnet Gateway" OVVERO: passo l'output del comando ipconfig al comando FINDSTR, dicendo che mi estragga SOLO le righe che contengono "Indirizzo", "Subnet" oppure "Gateway". Però il PIPING mi manderebbe in errore il comando FOR, se non fosse ESCAPED dal carattere ^. Infatti l'interprete BATCH analizzerebbe la richiesta come "tutto quello che si trova prima del PIPE è il primo comando sulla riga, tutto ciò che si trova dopo il secondo. Il comando terminerebbe con un erroraccio ininterpretabile: " %%a non atteso. ". :-)

Tutte le righe che seguono la parentesi aperta e che precedono la parentesi chiusa sono eseguite ciclicamente dal FOR, quindi per ogni riga dell'output del comando sopra descritto.

SET var!i!=%%b -> qui dico di impostare la variabile varX (dove X è il valore attuale della variabile !i! che abbiamo inizializzato prima del FOR e che al primo ciclo è 0) con la SECONDA variabile nell'analisi di FOR della riga, ovvero tutto ciò che è successivo al primo ":" della riga analizzata.

SET /A i=!i!+1 ->incremento la variabile !i! algebricamente (/A) di uno rispetto al suo valore attuale.

ed ecco spiegato il "trucco". Spero che vi sia utile in futuro! :-)


P.S.: problemi con gli spazi? non li volete? usate le sostituzioni. Es. !var0: =! ritornerà la variabile var0 senza spazi (spazio uguale niente).

--
Diego Castelli
Verona - Italy
-------------------------
MCSA 2003, MCTS Forefront, MCP
HP AIS, HP APS

Windows come Linux - Lo Scriptomane - livello MEDIO

Buongiorno a tutti, scrivo questo post per mostrare a tutti alcune funzionalità della shell dei comandi windows, che la rendono (combinata con gli altri linguaggi di script supportati, come vbscript e jscript) potente come la tanto chiacchierata shell di linux.
Tanto per cominciare voglio dire che io sono un bilingue dei sistemi operativi. Mi piacciono molti sistemi e uso volentieri le più disparate versioni di OS (non solo *NIX!) in base all'obiettivo che cerco di raggiungere.
Le mie competenze che voglio qui condividere mi hanno valso il soprannome di scriptomane, tra i miei colleghi, ed alcuni sistemisti linux con cui ho collaborato hanno osservato: ma tu usi windows come linux!
Oggi voglio parlare delle alternative windows batch al potentissimo comando unix GREP. Lo sapevate che anche in windows é possibile analizzare l'output di un comando, ad esempio, con le regular expressions? I comandi batch FIND e FINDSTR permettono l'uno uno startup semplice per chi non ha bisogno di regular expressions o ricerche multiple, l'altro lo stadio più avanzato della ricerca nei files, nelle directory e nell'output dalla pipe.
Per chi non lo sapesse, la pipe é un modo di redirezione dell'output che proviene dai sistemi *nix e che era già implementato in DOS da una certa versione.
Un semplice modo per passare l'output di un comando ad un secondo comando é
Comando1 | Comando2, ad esempio:
Netstat -n | FIND ":25 "
Mostrerà tutte le connessioni di rete attive sulla porta 25, sia che esse siano in ingresso, sia che siano in uscita.
Dir /A-D /B | Findstr /I /R "[sa].*[bg]\..* [a-fzx]*\..*"
Cerca tutti i files nella directory corrente che non sono directory (/A-D), con qualsiasi estensione e il cui nome
  1. cominci per s oppure per a e finisca per b oppure per g, con qualsiasi estensione.
  2. oppure contenga solo a, b, c, d, e, f, z oppure x, con qualsiasi estensione.
Notate lo spazio che separa le due regular expressions usate per analizzare l'output del comando DIR.


Ed ecco che abbiamo descritto una funzione evolutissima della shell command-line di Windows.
A mio avviso è il metodo perfetto per ottenere output filtrati ulteriormente analizzabili/utilizzabili da altri script.

Si può anche iserire i risultati in un ciclo for per operare azioni sulla base di ogni riga outputtata... ma questo ve lo dico in un altro post....


Ciao!