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

Mantenere lo spazio libero su disco è cruciale nella gestione dei server e dei sistemi. Come amministratori, non vorreste trovarvi impreparati di fronte a una situazione di ‘disco pieno’. Per assicurarti di essere al sicuro, dovresti imparare come utilizzare PowerShell per eliminare file!

In questo articolo, imparerai praticamente ogni modo per rimuovere file dai tuoi sistemi con PowerShell.

Cominciamo!

Prerequisiti

Questo articolo presenta esempi utilizzando PowerShell e se prevedi di seguirci, avrai bisogno dei seguenti.

Utilizzo del Cmdlet Remove-Item per eliminare file

Quando hai semplicemente bisogno di utilizzare PowerShell per eliminare un file, probabilmente imparerai immediatamente sul Remove-Item cmdlet. Questo cmdlet è lo standard de facto per rimuovere file con PowerShell.

Utilizzando Remove-Item combinato con il cmdlet Get-ChildItem per leggere file e cartelle e il potente pipeline di PowerShell, le cose possono davvero diventare un gioco da ragazzi.

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

Sapevi che il cmdlet Remove-Item ha un alias con il nome di del? Quando lavori in PowerShell, utilizzare Remove-Item o del eseguirà lo stesso comando.

Utilizzo di PowerShell per eliminare un file

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

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

L’esecuzione del codice sopra in PowerShell non mostrerebbe nulla sullo schermo a meno che non si verifichi un errore.

Utilizzo di PowerShell per eliminare tutti i file nella cartella

In questo esempio, il codice seguente 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 file. Get-ChildItem ignora le cartelle.

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

Il risultato dovrebbe assomigliare a questa schermata sottostante.

Successfully deleted all files in a folder

Utilizzo di 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 sottocartella, è 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

L’esecuzione del codice precedente costringe PowerShell a esaminare tutte le sottocartelle e recuperare tutti gli elenchi dei file. Il risultato sottostante mostra che il codice è riuscito a eliminare i file nella cartella superiore; tuttavia, non è riuscito a recuperare i file nelle sottocartelle.

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 il Get-ChildItem sta cercando di leggere supera la lunghezza massima del percorso di 260 caratteri.

La schermata sottostante mostra che il percorso o la directory e le relative sottodirectory esistono e un file di testo denominato InTooDeep.txt si trova nella sottodirectory 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 workaround per il problema del nome del percorso lungo. Il workaround consiste nell’utilizzare la versione Unicode del percorso. Invece di specificare il percorso in questo modo – C:\temp, utilizzare la versione Unicode in questo modo – ‘\\?\C:\temp’ per le cartelle situate localmente, o ‘\\?\UNC\<computername>\<share>\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 tiene conto del nome del percorso lungo, l’output di seguito mostra che PowerShell ha letto con successo 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 nome del percorso lungo non influisce su PowerShell 7.0. Con PowerShell 7.0, non c’è bisogno di utilizzare la versione Unicode del percorso perché supporta già nativamente i nomi dei 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.

Utilizzare PowerShell per Eliminare File Più Vecchi di x Giorni

Un altro esempio tipico di gestione dello spazio su disco è eliminare i file più vecchi di un numero specifico di giorni. Questo esempio è utile per rimuovere i vecchi file di registro, 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 sottostante, il Nome, il CreationTIme e il AgeInDays di ciascun file in c:\temp vengono mostrati.

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

Come si può 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 si conoscono i file da rimuovere, è possibile 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 sottostante, i file in C:\temp il cui valore CreationTime è più vecchio della soglia impostata verranno eliminati.

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

La riga successiva dopo la variabile $threshold farà:

  • Ottenere la raccolta di file situati nella cartella specificata nella variabile $path. In questo esempio, il percorso è C:\temp.
  • Filtrare l’output per includere solo i file il cui valore CreationTime è più vecchio del numero di giorni salvato nella variabile $threshold. In questo esempio, la soglia è di 14 giorni.
  • Passa l’elenco filtrato dei 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 esegui il codice sopra, vedrai un output come mostrato di seguito.

The script deleted the files older than 14 days

Notare che dalla schermata sopra, basandosi sul messaggio verbose, lo script ha eliminato solo cinque file più vecchi di 14 giorni. Per confermare che i file più recenti di 14 giorni esistono ancora, esegui 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 sotto conferma che Remove-Item non ha eliminato i file più recenti.

Newer files are left untouched

Utilizzare PowerShell per corrispondere ed eliminare i modelli di file

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

Nell’esempio successivo di seguito viene mostrato come eliminare i file che corrispondono 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 prudente è utilizzare prima Get-ChildItem per raccogliere l’elenco dei file da eliminare. Solo quando sei soddisfatto dell’elenco dei file da eliminare, puoi infine passare 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, Get-ChildItem restituisce un elenco di file che corrispondono al nome del file *.LOG.

Only files matching the *.log filename is returned

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

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

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

The file File_5.log was excluded

Quando sei già soddisfatto della raccolta di file che il tuo codice crea, puoi passare la raccolta di file al 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 il tuo obiettivo di eliminare solo i file che hai selezionato.

Deleting selected files

Eliminazione dei file utilizzando WMI in PowerShell

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

PowerShell è dotato di supporto per 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.

Utilizzo di 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. Utilizzare WQL richiede di escapare alcuni caratteri, incluso il backslash. E poiché il carattere di escape di WQL è anche il backslash, si ottengono i caratteri doppio-backslash – \\.

Eseguendo il codice sopra si ottiene il risultato mostrato nella dimostrazione sottostante. Le informazioni su C:\Temp\random.txt sono 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 si può vedere nello screenshot sotto, 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 di ReturnValue, si prega di fare riferimento a questo link – metodo Delete della classe CIM_DataFile

Inoltre, la schermata 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

Utilizzo di PowerShell e WMI per eliminare tutti i file nella cartella

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

Nel codice seguente, 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, le informazioni recuperate sui file in C:\temp vengono salvate nella variabile $file2delete. Visualizzando il valore(i) della variabile $file2delete viene mostrato l’output di seguito.

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

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

$file2delete | Invoke-CimMethod -Name Delete

Ricorda, il codice ReturnValue di 0 significa che l’operazione è stata eseguita con successo 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

Utilizzo di 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, è anche possibile controllare quali file vengono eliminati in base all’estensione.

Noterai nel codice qui sotto, questa volta la query ha una condizione aggiunta (Name LIKE '%.log). Questa condizione aggiunta significa che vengono restituiti solo i file che corrispondono all’estensione .LOG. Il segno percentuale (%) è un operatore LIKE di WQL che significa “Una stringa di zero o più caratteri”. In termini di programmazione, il % equivale 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 seguente mostra che prima dell’esecuzione del codice sopra, ci sono nove *.LOG file e solo un *.TXT file. Una volta che il codice ha finito di eseguire, 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 integrato in PowerShell come Get-ChildItem e Remove-Item per recuperare ed eliminare i file è molto più veloce rispetto all’utilizzo di WMI.

L’esempio qui sotto mostra il confronto tra l’utilizzo di WMI e il cmdlet integrato 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\ in modo ricorsivo utilizzando Get-ChildItem
Measure-Command { Get-ChildItem C:\Windows\Web\ -Recurse}

## Elenca tutti i file in C:\Windows\Web\ in modo ricorsivo utilizzando Get-CimInstance e la 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 seguente.

Get-ChildItem vs. Get-CimInstance with WMI Query

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

Hai anche 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 più breve.

Passaggi successivi

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

Sappi che dovresti sempre utilizzare i cmdlet Get-ChildItem e Remove-Item per rimuovere i file. Questi cmdlet integrati 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. Certamente, alcuni script già esistono a tale scopo; utilizzali come riferimento, ma se sei disposto a praticare e imparare, dovresti cercare di creare il tuo.

Lettura Ulteriore

Source:
https://adamtheautomator.com/powershell-delete-file/