Exclusão Eficiente de Arquivos com PowerShell: Remove-Item e WMI

Manter espaço livre no disco é crucial ao gerenciar servidores e sistemas. Como administradores, vocês não gostariam de serem pegos de surpresa por uma situação de ‘disco cheio’. Para garantir que estejam preparados, vocês devem aprender como usar o PowerShell para excluir arquivos!

Neste artigo, você aprenderá praticamente todas as maneiras de remover arquivos dos seus sistemas com o PowerShell.

Vamos começar!

Pré-requisitos

Este artigo apresenta exemplos usando o PowerShell, e se você pretende acompanhar, precisará do seguinte.

Usando o Cmdlet Remove-Item para Excluir Arquivos

Quando você simplesmente precisa usar o PowerShell para excluir um arquivo, provavelmente aprenderá imediatamente sobre o Remove-Item cmdlet. Este cmdlet é o padrão de facto para remover arquivos com o PowerShell.

Usando Remove-Item combinado com o cmdlet Get-ChildItem para ler arquivos e pastas e o poderoso pipeline do PowerShell pode realmente facilitar as coisas.

Relacionado: Get-ChildItem: Listando Arquivos, Registro, Certificados e Mais

Você sabia que o cmdlet Remove-Item tem um alias pelo nome de del? Ao trabalhar no PowerShell, usar Remove-Item ou del executará o mesmo comando.

Usando o PowerShell para Excluir um Arquivo

O primeiro exemplo que seria mais útil é o mais básico – ou seja, excluir um único arquivo. Para excluir apenas um único arquivo, você só precisa usar o comando abaixo. O código abaixo exclui o arquivo C:\temp\random.txt.

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

Executar o código acima no PowerShell não mostrará nada na tela, a menos que um erro seja encontrado.

Usando o PowerShell para Excluir Todos os Arquivos em uma Pasta

Neste exemplo, o código abaixo exclui todos os arquivos em uma pasta. O cmdlet Get-ChildItem direciona C:\temp com o parâmetro -Path. O parâmetro -File indica que o único tipo de item a ser incluído são arquivos. Get-ChildItem ignora pastas.

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

A saída deve se parecer com esta captura de tela abaixo.

Successfully deleted all files in a folder

Usando o PowerShell para Excluir Todos os Arquivos Recursivamente

O exemplo anterior apenas excluiu arquivos na pasta C:\temp. Se você precisar também excluir os arquivos dentro de cada subdiretório, você precisa adicionar o interruptor -Recurse ao cmdlet Get-ChildItem para obter todos os arquivos recursivamente.

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

Executar o código acima força o PowerShell a procurar em todas as subpastas e recuperar toda a lista de arquivos. A saída abaixo mostra que o código conseguiu excluir arquivos na pasta superior; no entanto, falhou em recuperar os arquivos nas subpastas.

Failed to retrieve files in sub-folders

Contornando o Problema do Caminho Longo

O erro mostrado acima indica que o PowerShell “não conseguiu encontrar uma parte do caminho”. Esse erro indica que o caminho que o cmdlet está tentando acessar não existe – o que é enganoso.

Neste caso, o erro ocorreu porque o caminho que o Get-ChildItem está tentando ler excede o comprimento máximo do caminho de 260 caracteres.

A captura de tela abaixo mostra que o caminho ou diretório e seus subdiretórios existem e um arquivo de texto chamado InTooDeep.txt está localizado no subdiretório mais inferior. A combinação de todos os caracteres que compõem os nomes de diretório aninhados cria um problema de caminho longo.

Nested directories creating a long path name

No Windows PowerShell 5.1, existe uma solução alternativa para o problema do nome longo do caminho. A solução alternativa é usar a versão Unicode do caminho. Em vez de especificar o caminho assim – C:\temp, use a versão Unicode assim – ‘\\?\C:\temp’ para pastas localizadas localmente, ou ‘\\?\UNC\<nome-do-computador>\<compartilhamento>\Temp’ se a pasta estiver localizada em um caminho UNC.

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

Usando o código modificado acima que atende ao nome longo do caminho, a saída abaixo mostra que o PowerShell leu o nome do caminho profundamente aninhado com sucesso e excluiu o arquivo.

Deleted the file with a long path name

Observe que o problema do nome longo do caminho não afeta o PowerShell 7.0. Com o PowerShell 7.0, não é necessário usar a versão Unicode do caminho porque ele já possui suporte integrado para nomes de caminho longo.

Se as pastas também precisarem ser excluídas, basta remover o parâmetro -File do cmdlet Get-ChildItem, e o PowerShell deve excluir todos os itens, incluindo arquivos e pastas.

Usando o PowerShell para Excluir Arquivos Mais Antigos Que x Dias

Outro exemplo típico de organização de espaço em disco é excluir arquivos que são mais antigos do que um número específico de dias. Este exemplo é útil para remover arquivos de log antigos, como aqueles gerados por servidores web IIS, para liberar espaço em disco.

Neste exemplo, existem arquivos em c:\temp que são mais antigos do que 14 dias. Usando o script abaixo, o Nome, CreationTIme, e AgeInDays de cada arquivo em c:\temp é mostrado.

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

Como você pode ver na captura de tela abaixo, existem arquivos que têm 15 dias de idade, 7 dias de idade e 0 dias de idade.

List of files in c:\temp

Agora que você sabe quais arquivos remover, você pode criar um script para excluir apenas os arquivos que são mais antigos do que um número específico de dias – neste caso, mais antigos do que 14 dias.

Neste exemplo de script abaixo, arquivos em C:\temp cujo valor de CreationTime é mais antigo do que o limite definido serão excluídos.

A primeira linha define o caminho para Get-ChildItem pesquisar. O caminho é salvo na variável $path. Em seguida, a segunda linha é onde o limite é especificado. O valor da variável $threshold é a idade em dias que o arquivo a ser excluído deve ter.

A próxima linha de código após a variável $threshold irá:

  • Obter a coleção de arquivos localizados na pasta especificada na variável $path. Neste exemplo, o caminho é C:\temp.
  • Filtrar a saída para incluir apenas arquivos cujo valor de CreationTime seja mais antigo do que o número de dias salvo na variável $threshold. Neste exemplo, o limite é de 14 dias.
  • Encaminhe a lista filtrada de arquivos para o valor Remove-Item para realizar a exclusão desses arquivos.
$path = 'C:\Temp'
$threshold = 14
Get-ChildItem -Path $path -File | Where-Object {$PSItem.CreationTime -lt (Get-Date).AddDays(-$threshold)} |Remove-Item -Verbose

Ao executar o código acima, você verá uma saída como mostrado abaixo.

The script deleted the files older than 14 days

Observe que, a partir da captura de tela acima, com base na mensagem verbose, o script só excluiu cinco arquivos mais antigos que 14 dias. Para confirmar que os arquivos mais novos que 14 dias ainda existem, execute o código abaixo para listá-los novamente.

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

O resultado abaixo confirma que Remove-Item não excluiu os arquivos mais novos.

Newer files are left untouched

Usando o PowerShell para combinar e excluir padrões de arquivos

Excluir todos os arquivos, independentemente do nome, tipo ou extensão, nem sempre é a melhor abordagem. Às vezes, você precisa excluir ou incluir explicitamente certos arquivos no processo de exclusão.

O próximo exemplo abaixo mostra como excluir os arquivos que correspondem ao nome do arquivo *.LOG. Uma maneira de fazer isso é usando o cmdlet Remove-Item diretamente com o uso do parâmetro -Include, como mostrado abaixo.

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

Outra maneira é, talvez, a abordagem cautelosa seja usar Get-ChildItem primeiro para coletar a lista de arquivos a serem excluídos. Somente quando você estiver satisfeito com a lista de arquivos para exclusão, você pode finalmente encaminhar a coleção para o cmdlet Remove-Item.

Por exemplo, o código abaixo obtém os arquivos *.LOG em c:\temp.

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

Como resultado do código acima, Get-ChildItem retorna uma lista de arquivos que correspondem ao nome do arquivo *.LOG.

Only files matching the *.log filename is returned

Mas, e se você quiser excluir um arquivo que contenha o número 5 em seu nome? Você pode fazer isso adicionando o parâmetro -Exclude como neste próximo código.

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

Como você excluiu o arquivo com o número 5, o resultado agora é diferente. Especificamente, o arquivo File_5.log não está mais na lista, como mostrado abaixo.

The file File_5.log was excluded

Quando você estiver satisfeito com a coleção de arquivos que seu código cria, então você pode encadear a coleção de arquivos no cmdlet Remove-Item para finalmente excluir esses arquivos.

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

Depois de executar seu código final, você terá alcançado seu objetivo de excluir apenas os arquivos que você selecionou.

Deleting selected files

Excluindo arquivos usando WMI no PowerShell

Agora que você tem uma boa compreensão de como usar o comum cmdlet Remove-Item para remover arquivos, vamos avançar para um caso de uso mais avançado; usando WMI.

O PowerShell vem com suporte para WMI. E o suporte para WMI significa que consultas e métodos WMI podem ser chamados de dentro do PowerShell. Sim, WMI não é apenas para scripts Visual Basic que os administradores usavam nos primeiros dias do Windows.

A Microsoft lançou cmdlets CIM específicos para WMI no PowerShell 3.0. Os cmdlets CIM que serão usados para excluir arquivos são o Get-CimInstance e Invoke-CimMethod.

Usando o PowerShell e WMI para excluir um arquivo

Este exemplo pressupõe que você conhece o caminho do arquivo específico a ser excluído. O cmdlet Get-CimInstance com a classe Cim_DataFile é usado para recuperar as informações sobre o arquivo a ser excluído, que é C:\Temp\random.txt.

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

No código acima, o parâmetro -Filter aceita uma consulta no formato WQL. O uso de WQL requer que você escape alguns caracteres, incluindo a barra invertida. E, como o caractere de escape WQL também é a barra invertida, resultando nos caracteres de barra invertida dupla – \\.

Executando o código acima produz o resultado mostrado na demonstração abaixo. As informações sobre C:\Temp\random.txt são salvas na variável $file2delete

Getting a file using WMI query and PowerShell

Agora que as informações para o arquivo C:\Temp\random.txt são recuperadas, o objeto resultante na variável $file2delete pode ser encaminhado para o cmdlet Invoke-CimMethod. O cmdlet Invoke-CimMethod tem um parâmetro chamado -Name, que representa o nome do método da classe Cim_DataFile.

$file2delete | Invoke-CimMethod -Name Delete

Como você pode ver na captura de tela abaixo, o ReturnValue mostra 0, o que significa que o comando foi bem-sucedido.

File successfully deleted using WMI and PowerShell

Para conhecer os possíveis códigos de ReturnValue, consulte este link – método Delete da classe CIM_DataFile

Além disso, a captura de tela abaixo mostra que após executar o método Invoke-CimMethod Delete(), o CIM apenas removeu o arquivo C:\Temp\random.txt. Ele não removeu os outros arquivos.

C:\Temp\random.txt file was deleted

Usando o PowerShell e o WMI para Excluir Todos os Arquivos em uma Pasta

No próximo exemplo, mostrarei como excluir todos os arquivos em uma pasta usando o PowerShell e o WMI. Os mesmos cmdlets usados no exemplo anterior, que são Get-CimInstance e Invoke-CimMethod, serão utilizados. Mas, desta vez, a consulta WQL recuperará todos os arquivos na pasta, em vez de apenas um arquivo específico.

No código a seguir, o cmdlet Get-CimInstance recupera todos os arquivos localizados em C:\temp. Como você pode ver abaixo, a consulta filtra as propriedades Drive e Path da classe Cim_DataFile.

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

Ao executar o código acima, as informações recuperadas sobre os arquivos em C:\temp são armazenadas na variável $file2delete. Visualizar o(s) valor(es) da variável $file2delete mostra a saída abaixo.

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

Agora, os valores armazenados na variável $file2delete podem ser direcionados para o Invoke-CimMethod para excluir todos os arquivos em c:\temp.

$file2delete | Invoke-CimMethod -Name Delete

Lembre-se, o código de ReturnValue 0 significa sucesso, e para cada arquivo no qual o método de exclusão foi chamado, terá seu próprio código de ReturnValue.

All files in c:\temp deleted using WMI

Usando PowerShell e WMI para Excluir Arquivos por Extensão

Você viu no exemplo anterior como excluir todos os arquivos em uma pasta, independentemente da extensão. No entanto, você também pode controlar quais arquivos serão excluídos com base na extensão.

Você notará no código abaixo que, desta vez, a consulta possui uma condição adicional (Name LIKE '%.log). Essa condição adicional significa que apenas os arquivos que correspondem à extensão .LOG são retornados. O sinal de percentual (%) é um operador LIKE WQL que significa “Uma cadeia de caracteres de zero ou mais caracteres”. Em termos de programação, o % é equivalente a um caractere curinga, que é o asterisco (*).

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

$file2delete | Invoke-CimMethod -Name Delete

A demonstração abaixo mostra que antes da execução do código acima, existem nove arquivos *.LOG e apenas um arquivo *.TXT. Uma vez que o código termina de ser executado, os arquivos *.LOG são excluídos e o arquivo *.TXT é o único arquivo restante na pasta.

Deleting files by extension using WMI

Comparando WMI e Remove-Item

Até agora neste tutorial, você obteve uma visão geral ampla de como usar o PowerShell para excluir arquivos. Você aprendeu sobre Remove-Item e também WMI. Ambos executam funções semelhantes, mas de maneiras muito diferentes.

Qual método você deve usar para excluir arquivos; Remove-Item ou WMI?

Usar um cmdlet embutido no PowerShell como Get-ChildItem e Remove-Item para recuperar e excluir arquivos é muito mais rápido do que quando se usa WMI.

O exemplo abaixo mostra a comparação ao usar WMI e o cmdlet integrado do PowerShell para obter a lista de arquivos no diretório C:\windows\web e seus subdiretórios.

## Listar todos os arquivos em C:\Windows\Web\ recursivamente usando Get-ChildItem
Measure-Command { Get-ChildItem C:\Windows\Web\ -Recurse}

## Listar todos os arquivos em C:\Windows\Web\ recursivamente usando Get-CimInstance e consulta WMI
Measure-Command { Get-CimInstance -ClassName Cim_DataFile -Filter "Drive = 'c:' AND Path = '\windows\web\%'"}

Ao executar o código acima no PowerShell, você verá a saída semelhante abaixo.

Get-ChildItem vs. Get-CimInstance with WMI Query

Como você pode ver na saída mostrada acima, listar os arquivos em C:\windows\web quase levou dez vezes mais tempo usando Get-CimInstance do que o tempo que levou para Get-ChildItem completar!

Além disso, você percebeu como a linha Get-ChildItem é muito mais curta do que Get-CimInstance? Não apenas você obtém uma execução mais rápida usando Get-ChildItem, mas também se beneficia de um código mais limpo e mais curto.

Próximos Passos

Neste artigo, você viu as duas maneiras diferentes de usar o PowerShell para excluir arquivos com cmdlets integrados e WMI/CIM.

Saiba que você sempre deve usar o cmdlet Get-ChildItem e Remove-Item para remover arquivos. Esses cmdlets integrados são mais flexíveis, mais fáceis e mais rápidos de usar do que quando se usa WMI.

Tente criar um script que possa realizar a limpeza do espaço em disco para você. Certamente, já existem alguns scripts com esse propósito; sinta-se à vontade para usá-los como referência, mas se estiver disposto a praticar e aprender, você deveria tentar criar o seu próprio.

Leitura Adicional

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