Nenhuma das respostas publicadas em 01/06/2018, com exceção da linha de comando única publicada por foxidrive , realmente excluiu todos os arquivos e todas as pastas / diretórios do Windows%PathToFolder%
. Essa é a razão para postar mais uma resposta com uma linha de comando única muito simples para excluir todos os arquivos e subpastas de uma pasta, bem como um arquivo em lotes com uma solução mais complexa, explicando por que todas as outras respostas foram publicadas em 01/06/2018 usando DEL e FOR com RD falhou ao limpar uma pasta completamente.
A solução simples de linha de comando simples que, é claro, também pode ser usada em um arquivo em lotes:
pushd "%PathToFolder%" 2>nul && ( rd /Q /S "%PathToFolder%" 2>nul & popd )
Esta linha de comando contém três comandos executados um após o outro.
O primeiro comando PUSHD coloca o caminho do diretório atual na pilha e, em seguida, cria%PathToFolder%
o diretório atual para a execução do processo de comando.
Isso funciona também para caminhos UNC por padrão, porque as extensões de comando são ativadas por padrão e, nesse caso, o PUSHD cria uma letra de unidade temporária que aponta para o recurso de rede especificado e altera a unidade e o diretório atuais, usando a letra da unidade recém-definida.
PUSHD gera a seguinte mensagem de erro para manipular STDERR se o diretório especificado não existir:
O sistema não consegue encontrar o caminho especificado.
Essa mensagem de erro é suprimida, redirecionando-a 2>nul
para o dispositivo NUL .
O próximo comando RD é executado apenas se a troca do diretório atual do processo de comando atual para o diretório especificado for bem-sucedida, ou seja, o diretório especificado existe.
O comando RD com as opções /Q
e /S
remove um diretório silenciosamente com todos os subdiretórios, mesmo que o diretório especificado contenha arquivos ou pastas com atributo oculto ou com conjunto de atributos somente leitura. O atributo do sistema nunca impede a exclusão de um arquivo ou pasta.
Não excluídos são:
Pastas usadas como o diretório atual para qualquer processo em execução. A árvore inteira de pastas dessa pasta não pode ser excluída se uma pasta for usada como o diretório atual para qualquer processo em execução.
Arquivos atualmente abertos por qualquer processo em execução com permissões de acesso a arquivos definidas no arquivo aberto para impedir a exclusão do arquivo enquanto aberto pelo aplicativo / processo em execução. Esse arquivo aberto impede também a exclusão de toda a árvore de pastas no arquivo aberto.
Arquivos / pastas nos quais o usuário atual não possui as permissões (NTFS) necessárias para excluir o arquivo / pasta, o que impede também a exclusão da árvore de pastas nesse arquivo / pasta.
O primeiro motivo para não excluir uma pasta é usado por esta linha de comando para excluir todos os arquivos e subpastas da pasta especificada, mas não a própria pasta. A pasta é transformada temporariamente no diretório atual para a execução do processo de comando, o que impede a exclusão da própria pasta. Obviamente, isso resulta na saída de uma mensagem de erro pelo comando RD :
O processo não pode acessar o arquivo porque está sendo usado por outro processo.
Arquivo é o termo errado aqui, pois, na realidade, a pasta está sendo usada por outro processo, o processo de comando atual que executou o comando RD . Bem, na realidade, uma pasta é para o sistema de arquivos um arquivo especial com diretório de atributos de arquivo que explica essa mensagem de erro. Mas não quero me aprofundar no gerenciamento do sistema de arquivos.
Essa mensagem de erro, como todas as outras mensagens de erro, que podem ocorrer devido aos três motivos mencionados acima, é suprimida, redirecionando-a 2>nul
do identificador STDERR para o dispositivo NUL .
O terceiro comando, POPD , é executado independentemente do valor de saída do comando RD .
O POPD exibe o caminho do diretório pressionado por PUSHD da pilha e altera o diretório atual para executar o processo de comando nesse diretório, ou seja, restaura o diretório atual inicial. O POPD exclui a letra da unidade temporária criada por PUSHD no caso de um caminho de pasta UNC.
Nota: O POPD pode silenciosamente falhar ao restaurar o diretório atual inicial, caso o diretório atual inicial tenha sido um subdiretório do diretório a ser limpo, o que não existe mais. Nesse caso especial, %PathToFolder%
permanece o diretório atual. Portanto, é aconselhável executar a linha de comando acima, não a partir de um subdiretório de %PathToFolder%
.
Mais um fato interessante :
tentei a linha de comando também usando um caminho UNC compartilhando o diretório local C:\Temp
com o nome do compartilhamento Temp
e usando o caminho UNC \\%COMPUTERNAME%\Temp\CleanTest
atribuído à variável de ambiente PathToFolder
no Windows 7. Se o diretório atual na execução da linha de comando for um subdiretório de um local compartilhado A pasta acessada usando o caminho UNC, ou seja C:\Temp\CleanTest\Subfolder1
, Subfolder1
é excluída pelo RD , e o próximo POPD falha silenciosamente ao criar C:\Temp\CleanTest\Subfolder1
novamente o diretório atual, resultando em Z:\CleanTest
permanecer como o diretório atual do processo de comando em execução. Portanto, nesse caso muito, muito especial, a letra da unidade temporária permanece até que o diretório atual seja alterado, por exemplo, comcd /D %SystemRoot%
para um diretório local realmente existente. Infelizmente, o POPD não sai com um valor maior 0 se não conseguir restaurar o diretório atual inicial, impossibilitando a detecção dessa condição de erro muito especial usando apenas o código de saída do POPD . No entanto, pode-se supor que ninguém nunca encontre esse caso de erro muito especial, pois os caminhos UNC geralmente não são usados para acessar arquivos e pastas locais.
Para entender ainda melhor os comandos usados, abra uma janela de prompt de comandos, execute os seguintes comandos e leia a ajuda exibida para cada comando com muito cuidado.
Linha única com vários comandos usando o arquivo em lotes do Windows explica os operadores &&
e &
usados aqui.
Em seguida, vejamos a solução de arquivos em lote usando o comando DEL para excluir arquivos %PathToFolder%
e FOR e RD para excluir as subpastas %PathToFolder%
.
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Clean the folder for temporary files if environment variable
rem PathToFolder is not defined already outside this batch file.
if not defined PathToFolder set "PathToFolder=%TEMP%"
rem Remove all double quotes from folder path.
set "PathToFolder=%PathToFolder:"=%"
rem Consisted the folder path only of double quotes?
if not defined PathToFolder goto EndCleanFolder
rem Remove a backslash at end of folder path.
if "%PathToFolder:~-1%" == "\" set "PathToFolder=%PathToFolder:~0,-1%"
rem Consisted folder path only of a backslash (with one or more double quotes)?
if not defined PathToFolder goto EndCleanFolder
rem Delete all files in specified folder including files with hidden
rem or read-only attribute set, except the files currently opened by
rem a running process which prevents deletion of the file while being
rem opened by the application, or on which the current user has not
rem the required permissions to delete the file.
del /A /F /Q "%PathToFolder%\*" >nul 2>nul
rem Delete all subfolders in specified folder including those with hidden
rem attribute set recursive with all files and subfolders, except folders
rem being the current directory of any running process which prevents the
rem deletion of the folder and all folders above, folders containing a file
rem opened by the application which prevents deletion of the file and the
rem entire folder structure to this file, or on which the current user has
rem not the required permissions to delete a folder or file in folder tree
rem to delete.
for /F "eol=| delims=" %%I in ('dir "%PathToFolder%\*" /AD /B 2^>nul') do rd /Q /S "%PathToFolder%\%%I" 2>nul
:EndCleanFolder
endlocal
O arquivo em lotes primeiro garante que a variável de ambiente PathToFolder
seja realmente definida com um caminho de pasta sem aspas duplas e sem uma barra invertida no final. A barra invertida no final não seria um problema, mas as aspas duplas no caminho de uma pasta podem ser problemáticas, pois o valor de PathToFolder
é concatenado com outras seqüências durante a execução do arquivo em lotes.
Importante são as duas linhas:
del /A /F /Q "%PathToFolder%\*" >nul 2>nul
for /F "eol=| delims=" %%I in ('dir "%PathToFolder%\*" /AD /B 2^>nul') do rd /Q /S "%PathToFolder%\%%I" 2>nul
O comando DEL é usado para excluir todos os arquivos no diretório especificado.
- A opção
/A
é necessária para o processo de realmente todos os arquivos, incluindo arquivos com o atributo escondido que DEL iria ignorar sem o uso de opção /A
.
- A opção
/F
é necessária para forçar a exclusão de arquivos com o conjunto de atributos somente leitura.
- A opção
/Q
é necessária para executar uma exclusão silenciosa de vários arquivos sem avisar o usuário se vários arquivos devem ser realmente excluídos.
>nul
é necessário redirecionar a saída dos nomes de arquivo gravados para manipular STDOUT para o dispositivo NUL, que não pode ser excluído porque um arquivo está aberto no momento ou o usuário não tem permissão para excluir o arquivo.
2>nul
é necessário redirecionar a saída da mensagem de erro para cada arquivo que não pode ser excluído do identificador STDERR para o dispositivo NUL .
Os comandos FOR e RD são usados para remover todos os subdiretórios no diretório especificado. Mas for /D
não é usado porque FOR está ignorando, neste caso, subdiretórios com o conjunto de atributos ocultos. Por esse motivo, for /F
é usado para executar a seguinte linha de comando em um processo de comando separado iniciado em segundo plano com %ComSpec% /c
:
dir "%PathToFolder%\*" /AD /B 2>nul
DIR produz em formato simples por causa das /B
entradas de diretório com atributo D
, ou seja, os nomes de todos os subdiretórios no diretório especificado, independentes de outros atributos, como o atributo oculto sem um caminho. 2>nul
é usado para redirecionar a mensagem de erro emitida pelo DIR em nenhum diretório encontrado do identificador STDERR para o dispositivo NUL .
O operador de redirecionamento >
deve ser escapado com o caractere de intercalação ^
, na linha de comando FOR para ser interpretado como um caractere literal quando o interpretador de comando do Windows processar essa linha de comando antes de executar o comando FOR que executa a dir
linha de comando incorporada em um processo de comando separado iniciado no fundo.
FOR processa a saída capturada gravada para manipular STDOUT de um processo de comando iniciado, que são os nomes dos subdiretórios sem caminho e nunca são colocados entre aspas duplas.
A opção FOR with /F
ignora as linhas vazias que não ocorrem aqui, pois o DIR with option /B
não gera linhas vazias.
FOR também ignoraria as linhas começando com um ponto-e-vírgula, que é o caractere de fim de linha padrão. Um nome de diretório pode começar com um ponto e vírgula. Por esse motivo, eol=|
é usado para definir o caractere da barra vertical como o caractere de fim de linha que nenhum diretório ou arquivo pode ter em seu nome.
FOR dividiria a linha em substrings usando espaço e tab horizontal como delimitadores e atribuiria apenas a primeira string delimitada por espaço / tabulação à variável de loop especificada I
. Esse comportamento de divisão não é desejado aqui porque um nome de diretório pode conter um ou mais espaços. Portanto, delims=
é usado para definir uma lista vazia de delimitadores para desativar o comportamento de divisão de linha e ser atribuído à variável de loop I
, sempre o nome completo do diretório.
O comando FOR executa o comando RD para cada nome de diretório sem um caminho, motivo pelo qual, na linha de comando do RD , o caminho da pasta deve ser especificado novamente, o que é concatenado com o nome da subpasta.
Para entender os comandos usados e como eles funcionam, abra uma janela do prompt de comandos, execute os comandos a seguir e leia inteiramente todas as páginas de ajuda exibidas para cada comando com muito cuidado.
del /?
dir /?
echo /?
endlocal /?
for /?
goto /?
if /?
rd /?
rem /?
set /?
setlocal /?