Eliminazione efficiente dei file con PowerShell: Remove-Item e WMI

Mantenere lo spazio libero sul disco è fondamentale nella gestione di server e sistemi. Come amministratori, non vorreste trovarvi impreparati di fronte alla situazione di ‘disco pieno’. Per assicurarvi di essere al sicuro, dovreste imparare come utilizzare PowerShell per eliminare file!

In questo articolo, imparerete praticamente ogni modo per rimuovere file dai vostri sistemi con PowerShell.

Iniziamo!

Prerequisiti

Questo articolo presenta esempi utilizzando PowerShell e, se avete intenzione di seguirci, avrete bisogno dei seguenti elementi.

Utilizzare il cmdlet Remove-Item per eliminare file

Quando avete semplicemente bisogno di utilizzare PowerShell per eliminare un file, probabilmente scoprirete immediatamente il cmdlet Remove-Item. Questo cmdlet è lo standard de facto per la rimozione di file con PowerShell.

Utilizzando Remove-Item combinato con il cmdlet Get-ChildItem per leggere file e cartelle e la potente pipeline di PowerShell, le cose possono diventare molto più semplici.

Collegato: Get-ChildItem: Elenco di file, Registro, Certificati e altro ancora

Sapevate che il cmdlet Remove-Item ha un alias chiamato del? Quando si lavora in PowerShell, utilizzare Remove-Item o del eseguirà lo stesso comando.

Utilizzare PowerShell per eliminare un file

Il primo esempio che sarebbe più utile è il più basilare – ovvero, eliminare un singolo file. Per eliminare solo un singolo file, è sufficiente utilizzare il comando di seguito. Il codice di seguito elimina il file C:\temp\random.txt.

Remove-Item -Path C:\temp\random.txt

Eseguendo il codice sopra in PowerShell non mostrerà nulla sullo schermo a meno che non si verifichi un errore.

Utilizzare PowerShell per eliminare tutti i file in una cartella

In questo esempio, il codice di seguito elimina tutti i file in una cartella. Il cmdlet Get-ChildItem si rivolge a C:\temp con il parametro -Path. Il parametro -File indica che l’unico tipo di elemento da includere sono i file. Get-ChildItem ignora le cartelle.

Get-ChildItem -Path C:\temp -File | Remove-Item -Verbose

L’output dovrebbe apparire come nella schermata sottostante.

Successfully deleted all files in a folder

Utilizzare PowerShell per eliminare tutti i file in modo ricorsivo

L’esempio precedente ha eliminato solo i file nella cartella C:\temp. Se è necessario eliminare anche i file all’interno di ogni sottodirectory, è necessario aggiungere lo switch -Recurse al cmdlet Get-ChildItem per ottenere tutti i file in modo ricorsivo.

Get-ChildItem -Path C:\temp -File -Recurse | Remove-Item -Verbose

Eseguendo il codice sopra, PowerShell verrà obbligato a cercare in tutte le sottodirectory e recuperare l’elenco completo dei file. L’output sottostante mostra che il codice è riuscito a eliminare i file nella cartella principale; tuttavia, non è riuscito a recuperare i file nelle sottodirectory.

Failed to retrieve files in sub-folders

Risolvere il problema del percorso lungo

L’errore mostrato sopra indica che PowerShell “non è stato possibile trovare una parte del percorso”. Quell’errore indica che il percorso a cui il cmdlet sta cercando di accedere non esiste – il che è fuorviante.

In questo caso, l’errore è dovuto al fatto che il percorso che Get-ChildItem sta cercando di leggere supera la lunghezza massima del percorso di 260 caratteri.

Nella schermata sottostante si può vedere che il percorso o la cartella e le sue sottocartelle esistono e un file di testo chiamato InTooDeep.txt si trova nella sottocartella più profonda. La combinazione di tutti i caratteri che compongono i nomi delle directory nidificate crea un problema di percorso lungo.

Nested directories creating a long path name

In Windows PowerShell 5.1, c’è un modo per aggirare il problema del percorso lungo. Il trucco consiste nell’utilizzare la versione Unicode del percorso. Invece di specificare il percorso in questo modo – C:\temp, utilizzare la versione Unicode come segue – ‘\\?\C:\temp’ per le cartelle situate localmente, o ‘\\?\UNC\\\Temp’ se la cartella si trova in un percorso UNC.

Get-ChildItem -Path '\\?\C:\temp' -File -Recurse | Remove-Item -Verbose

Utilizzando il codice modificato sopra che gestisce il nome del percorso lungo, l’output sottostante mostra che PowerShell ha letto correttamente il nome del percorso profondamente nidificato ed ha eliminato il file.

Deleted the file with a long path name

Si noti che il problema del percorso lungo non influisce su PowerShell 7.0. Con PowerShell 7.0, non è necessario utilizzare la versione Unicode del percorso perché ha già il supporto integrato per i percorsi lunghi.

Se è necessario eliminare anche le cartelle, basta rimuovere il parametro -File dal cmdlet Get-ChildItem, e PowerShell dovrebbe eliminare tutti gli elementi, inclusi file e cartelle.

Utilizzando PowerShell per eliminare i file più vecchi di x giorni

Un altro esempio tipico di pulizia dello spazio su disco è l’eliminazione dei file più vecchi di un numero specifico di giorni. Questo esempio è utile per rimuovere vecchi file di log, come quelli generati dai server web IIS, per liberare spazio su disco.

In questo esempio, ci sono file in c:\temp che sono più vecchi di 14 giorni. Utilizzando lo script di seguito, vengono mostrati il Nome, il CreationTime e l’EtàInGiorni di ogni file in c:\temp.

Get-ChildItem c:\temp | Select-Object Name,CreationTime,@{n='AgeInDays';e={(New-TimeSpan -Start $PSItem.CreationTime).Days}}

Come puoi vedere nella schermata sottostante, ci sono file che hanno 15 giorni di età, 7 giorni di età e 0 giorni di età.

List of files in c:\temp

Ora che conosci i file da eliminare, puoi creare uno script per eliminare solo i file più vecchi di un numero specifico di giorni, in questo caso più vecchi di 14 giorni.

In questo esempio di script di seguito, i file in C:\temp il cui valore di CreationTime è più vecchio della soglia impostata verranno eliminati.

La prima riga definisce il percorso su cui Get-ChildItem dovrà cercare. Il percorso viene salvato nella variabile $path. Poi, la seconda riga è dove viene specificata la soglia. Il valore della variabile $threshold rappresenta l’età in giorni che il file da eliminare deve avere.

La riga di codice successiva alla variabile $threshold farà il seguente:

  • Otterrà la collezione di file presenti nella cartella specificata nella variabile $path. In questo esempio, il percorso è C:\temp.
  • Filtrerà l’output includendo solo i file il cui valore di CreationTime è più vecchio del numero di giorni salvato nella variabile $threshold. In questo esempio, la soglia è di 14 giorni.
  • Passa la lista filtrata di file al valore Remove-Item per eseguire l’eliminazione di quei file.
$path = 'C:\Temp'
$threshold = 14
Get-ChildItem -Path $path -File | Where-Object {$PSItem.CreationTime -lt (Get-Date).AddDays(-$threshold)} |Remove-Item -Verbose

Quando si esegue il codice sopra riportato, verrà visualizzato un output come mostrato di seguito.

The script deleted the files older than 14 days

Si noti che nella schermata sopra riportata, in base al messaggio dettagliato, lo script ha eliminato solo cinque file più vecchi di 14 giorni. Per confermare che i file più recenti di 14 giorni esistano ancora, eseguire il codice di seguito per elencarli nuovamente.

Get-ChildItem c:\temp | Select-Object Name,CreationTime,@{n='AgeInDays';e={(New-TimeSpan -Start $PSItem.CreationTime).Days}}

Il risultato riportato di seguito conferma che Remove-Item non ha eliminato i file più recenti.

Newer files are left untouched

Utilizzo di PowerShell per corrispondere ed eliminare modelli di file

Eliminare tutti i file, indipendentemente dal nome, tipo o estensione, non è sempre l’approccio migliore. A volte è necessario escludere o includere esplicitamente determinati file nel processo di eliminazione.

L’esempio successivo mostra come eliminare i file corrispondenti al nome del file *.LOG. Un modo per farlo è utilizzare direttamente il cmdlet Remove-Item con l’uso del parametro -Include, come mostrato di seguito.

Remove-Item -Path C:\temp\* -Include *.log

Un altro modo, forse l’approccio più cauto, è utilizzare prima Get-ChildItem per raccogliere l’elenco dei file da eliminare. Solo quando si è soddisfatti dell’elenco dei file da eliminare, è possibile passare infine la raccolta al cmdlet Remove-Item.

Ad esempio, il codice di seguito ottiene i file *.LOG in c:\temp.

Get-ChildItem -Path C:\temp\* -Include *.log

Come risultato del codice sopra riportato, Get-ChildItem restituisce un elenco di file corrispondenti al nome del file *.LOG.

Only files matching the *.log filename is returned

Ma, cosa succede se si desidera escludere un file che contiene il numero 5 nel suo nome? È possibile farlo aggiungendo il parametro -Exclude come nel codice successivo.

Get-ChildItem -Path C:\temp\* -Include *.log -Exclude *5*

Dato che hai escluso il file con il numero 5, il risultato è diverso. In particolare, il file File_5.log non è più presente nell’elenco, come mostrato di seguito.

The file File_5.log was excluded

Quando sei soddisfatto della raccolta di file che il tuo codice crea, puoi inviare la raccolta di file all’cmdlet Remove-Item per eliminare definitivamente quei file.

Get-ChildItem -Path C:\temp\* -Include *.log -Exclude *5* | Remove-Item -Verbose

Dopo aver eseguito il tuo codice finale, avrai raggiunto l’obiettivo di eliminare solo i file selezionati.

Deleting selected files

Eliminazione dei file utilizzando WMI in PowerShell

Ora che hai una buona comprensione dell’utilizzo dell’comune cmdlet Remove-Item per rimuovere i file, passiamo a un caso d’uso più avanzato; l’utilizzo di WMI.

PowerShell supporta WMI. E il supporto per WMI significa che le query e i metodi WMI possono essere chiamati da PowerShell. Sì, WMI non è solo per script Visual Basic che gli amministratori usavano nei primi giorni di Windows.

Microsoft ha rilasciato cmdlet CIM specifici per WMI in PowerShell 3.0. I cmdlet CIM che verranno utilizzati per eliminare i file sono Get-CimInstance e Invoke-CimMethod.

Utilizzando PowerShell e WMI per eliminare un file

Questo esempio presuppone che tu conosca il percorso del file specifico da eliminare. Il cmdlet Get-CimInstance con la classe Cim_DataFile viene utilizzato per recuperare le informazioni sul file da eliminare, che è C:\Temp\random.txt.

$file2delete = Get-CimInstance -ClassName Cim_DataFile -Filter "Name = 'C:\Temp\random.txt'"
 $file2delete

Nel codice sopra, il parametro -Filter accetta una query nel formato WQL. L’utilizzo di WQL richiede l’escape di alcuni caratteri, inclusa la barra rovesciata. E poiché il carattere di escape di WQL è anche la barra rovesciata, ne risultano caratteri doppi – \\.

L’esecuzione del codice sopra produce il risultato mostrato nella demo di seguito. Le informazioni su C:\Temp\random.txt vengono salvate nella variabile $file2delete.

Getting a file using WMI query and PowerShell

Ora che le informazioni sul file C:\Temp\random.txt sono state recuperate, l’oggetto risultante nella variabile $file2delete può essere inviato al cmdlet Invoke-CimMethod. Il cmdlet Invoke-CimMethod ha un parametro chiamato -Name, che rappresenta il nome del metodo della classe Cim_DataFile.

$file2delete | Invoke-CimMethod -Name Delete

Come puoi vedere nella schermata di seguito, il valore di ReturnValue mostra 0, il che significa che il comando è stato eseguito con successo.

File successfully deleted using WMI and PowerShell

Per conoscere i possibili codici ReturnValue, consulta questo link: Metodo Delete della classe CIM_DataFile

Inoltre, lo screenshot sottostante mostra che dopo aver eseguito il metodo Invoke-CimMethod Delete(), CIM ha rimosso solo il file C:\Temp\random.txt. Non ha rimosso gli altri file.

C:\Temp\random.txt file was deleted

Utilizzando PowerShell e WMI per eliminare tutti i file in una cartella

In questo prossimo esempio, ti mostrerò come eliminare tutti i file in una cartella utilizzando PowerShell e WMI. Verranno utilizzati gli stessi cmdlet utilizzati nell’esempio precedente, ovvero Get-CimInstance e Invoke-CimMethod. Tuttavia, questa volta, la query WQL recupererà tutti i file nella cartella anziché solo un file specifico.

In questo codice successivo, il cmdlet Get-CimInstance recupera tutti i file situati in C:\temp. Come puoi vedere di seguito, la query filtra le proprietà Drive e Path della classe Cim_DataFile.

$file2delete = Get-CimInstance -ClassName Cim_DataFile -Filter "Drive = 'c:' AND Path = '\\temp\\'"

Eseguendo il codice sopra riportato, le informazioni recuperate sui file in C:\temp vengono salvate nella variabile $file2delete. La visualizzazione del valore/i della variabile $file2delete mostra l’output sottostante.

List of all folders found in c:\temp using WMI

Ora, i valori memorizzati nella variabile $file2delete possono essere inviati in input al cmdlet Invoke-CimMethod per eliminare tutti i file in c:\temp.

$file2delete | Invoke-CimMethod -Name Delete

Ricorda, il codice ReturnValue 0 significa che l’operazione è riuscita e per ogni file su cui è stata chiamata il metodo di eliminazione avrà il proprio codice ReturnValue.

All files in c:\temp deleted using WMI

Utilizzando PowerShell e WMI per eliminare file per estensione

Hai visto nell’esempio precedente come eliminare tutti i file in una cartella indipendentemente dall’estensione. Tuttavia, puoi anche controllare quali file vengono eliminati in base all’estensione.

Noterai nel codice sottostante, questa volta la query ha una condizione aggiuntiva (Name LIKE '%.log). Questa condizione aggiuntiva significa che vengono restituiti solo i file che corrispondono all’estensione .LOG. Il segno di percentuale (%) è un operatore WQL LIKE che significa “Una stringa di zero o più caratteri”. In termini di programmazione, il segno di percentuale % è equivalente a un carattere jolly, che è il carattere asterisco (*).

$file2delete = Get-CimInstance -ClassName cim_datafile `
-Filter "Drive = 'c:' AND Path = '\\temp\\' AND Name LIKE '%.log'"

$file2delete | Invoke-CimMethod -Name Delete

La dimostrazione sottostante mostra che prima dell’esecuzione del codice sopra riportato, ci sono nove file *.LOG e solo un file *.TXT. Una volta terminata l’esecuzione del codice, i file *.LOG vengono eliminati e l’unico file rimasto nella cartella è il file *.TXT.

Deleting files by extension using WMI

Confronto tra WMI e Remove-Item

Fino ad ora in questo tutorial, hai ottenuto una panoramica generale su come utilizzare PowerShell per eliminare file. Hai appreso su Remove-Item e anche su WMI. Entrambi svolgono funzioni simili ma in modo molto diverso.

Quale metodo dovresti utilizzare per eliminare i file; Remove-Item o WMI?

Utilizzare un cmdlet incorporato in PowerShell, come Get-ChildItem e Remove-Item, per recuperare ed eliminare file è molto più veloce rispetto all’utilizzo di WMI.

L’esempio qui sotto mostra il confronto tra l’utilizzo di WMI e il cmdlet incorporato di PowerShell per ottenere l’elenco dei file nella directory C:\windows\web e nelle sue sottodirectory.

## Elenca tutti i file in C:\Windows\Web\ ricorsivamente usando Get-ChildItem
Measure-Command { Get-ChildItem C:\Windows\Web\ -Recurse}

## Elenca tutti i file in C:\Windows\Web\ ricorsivamente usando Get-CimInstance e una query WMI
Measure-Command { Get-CimInstance -ClassName Cim_DataFile -Filter "Drive = 'c:' AND Path = '\windows\web\%'"}

Quando esegui il codice sopra in PowerShell, vedrai un output simile a quello mostrato di seguito.

Get-ChildItem vs. Get-CimInstance with WMI Query

Come puoi vedere dall’output mostrato sopra, l’elenco dei file in C:\windows\web ha richiesto quasi dieci volte più tempo utilizzando Get-CimInstance rispetto a quanto impiegato da Get-ChildItem per completare l’operazione!

Inoltre, hai notato come la riga Get-ChildItem sia molto più breve di Get-CimInstance? Non solo ottieni un’esecuzione più veloce utilizzando Get-ChildItem, ma beneficerai anche di un codice più pulito e conciso.

Passaggi successivi

In questo articolo hai visto i due diversi modi in cui puoi usare PowerShell per eliminare file con cmdlet incorporati e WMI/CIM.

Ricorda che dovresti sempre utilizzare i cmdlet Get-ChildItem e Remove-Item per rimuovere i file. Questi cmdlet incorporati sono più flessibili, più facili e più veloci da usare rispetto all’utilizzo di WMI.

Prova a creare uno script che possa gestire lo spazio su disco per te. Certo, già esistono degli script a tale scopo; per tutti i mezzi, usali come riferimento, ma se sei disposto a pratica e imparare, dovresti provare a crearne uno tuo.

Ulteriori Letture

Source:
https://adamtheautomator.com/powershell-to-delete-files/