Nessuna delle risposte pubblicate il 01/06/2018, ad eccezione della singola riga di comando pubblicata da foxidrive , ha effettivamente eliminato tutti i file e tutte le cartelle / directory in %PathToFolder%
. Questo è il motivo per pubblicare un'altra risposta con una riga di comando singola molto semplice per eliminare tutti i file e le sottocartelle di una cartella, nonché un file batch con una soluzione più complessa che spiega perché tutte le altre risposte pubblicate il 01/06/2018 utilizzando DEL e FOR con RD non è riuscito a ripulire completamente una cartella.
La semplice soluzione a riga di comando singola che ovviamente può essere utilizzata anche in un file batch:
pushd "%PathToFolder%" 2>nul && ( rd /Q /S "%PathToFolder%" 2>nul & popd )
Questa riga di comando contiene tre comandi eseguiti uno dopo l'altro.
Il primo comando PUSHD inserisce nello stack il percorso della directory corrente e successivamente crea %PathToFolder%
la directory corrente per l'esecuzione del processo di comando.
Questo funziona anche per i percorsi UNC per impostazione predefinita a causa delle estensioni dei comandi abilitate per impostazione predefinita e in questo caso PUSHD crea una lettera di unità temporanea che punta a quella risorsa di rete specificata e quindi cambia l'unità e la directory correnti, utilizzando la lettera di unità appena definita.
PUSHD restituisce il seguente messaggio di errore per gestire STDERR se la directory specificata non esiste affatto:
Il sistema non può trovare il percorso specificato.
Questo messaggio di errore viene eliminato reindirizzandolo 2>nul
al dispositivo NUL .
Il comando successivo RD viene eseguito solo se la modifica della directory corrente per il processo di comando corrente nella directory specificata ha avuto esito positivo, ovvero la directory specificata esiste affatto.
Il comando RD con le opzioni /Q
e /S
rimuove silenziosamente una directory con tutte le sottodirectory anche se la directory specificata contiene file o cartelle con attributo nascosto o con set di attributi di sola lettura. L'attributo di sistema non impedisce mai l'eliminazione di un file o una cartella.
Non cancellati sono:
Cartelle utilizzate come directory corrente per qualsiasi processo in esecuzione. L'intero albero delle cartelle in tale cartella non può essere eliminato se una cartella viene utilizzata come directory corrente per qualsiasi processo in esecuzione.
File attualmente aperti da qualsiasi processo in esecuzione con autorizzazioni di accesso ai file impostate su file aperto per impedire l'eliminazione del file durante l'apertura dall'applicazione / processo in esecuzione. Tale file aperto impedisce anche l'eliminazione dell'intero albero delle cartelle nel file aperto.
File / cartelle in cui l'utente corrente non dispone delle autorizzazioni necessarie (NTFS) per eliminare il file / cartella che impedisce anche l'eliminazione dell'albero delle cartelle in questo file / cartella.
Il primo motivo per non eliminare una cartella viene utilizzato da questa riga di comando per eliminare tutti i file e le sottocartelle della cartella specificata, ma non la cartella stessa. La cartella viene temporaneamente trasformata nella directory corrente per l'esecuzione del processo di comando che impedisce l'eliminazione della cartella stessa. Ovviamente ciò comporta l'output di un messaggio di errore dal comando RD :
Il processo non può accedere al file perché è utilizzato da un altro processo.
File è il termine sbagliato qui poiché in realtà la cartella viene utilizzata da un altro processo, l'attuale processo di comando che ha eseguito il comando RD . Beh, in realtà, una cartella è per il file system un file speciale con attributo di file directory che spiega questo messaggio di errore. Ma non voglio approfondire troppo la gestione del file system.
Questo messaggio di errore, come tutti gli altri messaggi di errore, che potrebbero verificarsi a causa dei tre motivi sopra descritti, viene eliminato reindirizzandolo con 2>nul
da STDERR a dispositivo NUL .
Il terzo comando, POPD , viene eseguito indipendentemente dal valore di uscita del comando RD .
POPD estrae il percorso della directory inviato da PUSHD dallo stack e modifica la directory corrente per l'esecuzione del processo di comando in questa directory, ovvero ripristina la directory corrente iniziale. POPD elimina la lettera di unità temporanea creata da PUSHD nel caso di un percorso di cartella UNC.
Nota: POPD può non riuscire a ripristinare silenziosamente la directory corrente iniziale nel caso in cui la directory corrente iniziale fosse una sottodirectory della directory da ripulire che non esiste più. In questo caso speciale %PathToFolder%
rimane la directory corrente. Quindi è consigliabile eseguire la riga di comando sopra non da una sottodirectory di %PathToFolder%
.
Un altro fatto interessante :
ho provato la riga di comando anche utilizzando un percorso UNC condividendo la directory locale C:\Temp
con il nome di condivisione Temp
e utilizzando il percorso UNC \\%COMPUTERNAME%\Temp\CleanTest
assegnato alla variabile di ambiente PathToFolder
su Windows 7. Se la directory corrente in esecuzione sulla riga di comando è una sottodirectory di un locale condiviso la cartella a cui si accede tramite il percorso UNC, ovvero C:\Temp\CleanTest\Subfolder1
, Subfolder1
viene eliminata da RD e il POPD successivo non riesce in modo silenzioso a rendere C:\Temp\CleanTest\Subfolder1
nuovamente la directory corrente risultante nel Z:\CleanTest
rimanere come directory corrente per il processo di comando in esecuzione. Quindi, in questo caso molto particolare, la lettera di unità temporanea rimane fino a quando la directory corrente non viene modificata, ad esempiocd /D %SystemRoot%
in una directory locale realmente esistente. Sfortunatamente POPD non esce con un valore maggiore di 0 se non riesce a ripristinare la directory corrente iniziale rendendo impossibile rilevare questa condizione di errore molto speciale usando solo il codice di uscita di POPD . Tuttavia, si può supporre che nessuno abbia mai incontrato questo caso di errore molto speciale poiché i percorsi UNC di solito non vengono utilizzati per accedere a file e cartelle locali.
Per comprendere ancora meglio i comandi utilizzati, aprire una finestra del prompt dei comandi, eseguire lì i seguenti comandi e leggere con attenzione la guida visualizzata per ciascun comando.
Una riga con più comandi che utilizzano il file batch di Windows spiega gli operatori &&
e &
qui utilizzati.
Ora esaminiamo la soluzione di file batch utilizzando il comando DEL per eliminare i file %PathToFolder%
e FOR e RD per eliminare le sottocartelle %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
Il file batch si assicura innanzitutto che la variabile di ambiente PathToFolder
sia realmente definita con un percorso di cartella senza virgolette doppie e senza una barra rovesciata alla fine. La barra rovesciata alla fine non sarebbe un problema, ma le doppie virgolette nel percorso di una cartella potrebbero essere problematiche a causa del valore di PathToFolder
concatenato con altre stringhe durante l'esecuzione del file batch.
Importanti sono le due linee:
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
Il comando DEL viene utilizzato per eliminare tutti i file nella directory specificata.
- L'opzione
/A
è necessaria per elaborare realmente tutti i file inclusi i file con l'attributo nascosto che DEL ignorerebbe senza usare l'opzione /A
.
- L'opzione
/F
è necessaria per forzare la cancellazione dei file con l'attributo di sola lettura impostato.
- L'opzione
/Q
è necessaria per eseguire una cancellazione silenziosa di più file senza richiedere all'utente se è necessario eliminare più file.
>nul
è necessario reindirizzare l'output dei nomi dei file scritti per gestire STDOUT sul dispositivo NUL di cui non è possibile eliminare perché un file è attualmente aperto o l'utente non ha l'autorizzazione per eliminare il file.
2>nul
è necessario reindirizzare l'output del messaggio di errore per ciascun file che non può essere eliminato dall'handle STDERR al dispositivo NUL .
I comandi FOR e RD vengono utilizzati per rimuovere tutte le sottodirectory nella directory specificata. Ma for /D
non viene utilizzato perché FOR ignora in questo caso le sottodirectory con l'attributo nascosto impostato. Per questo motivo for /F
viene utilizzato per eseguire la seguente riga di comando in un processo di comando separato avviato in background con %ComSpec% /c
:
dir "%PathToFolder%\*" /AD /B 2>nul
DIR restituisce in formato non elaborato a causa delle /B
voci della directory con attributo D
, ovvero i nomi di tutte le sottodirectory nella directory specificata indipendenti su altri attributi come l'attributo nascosto senza un percorso. 2>nul
viene utilizzato per reindirizzare il messaggio di errore generato da DIR su nessuna directory trovata dall'handle STDERR al dispositivo NUL .
L'operatore di reindirizzamento >
deve essere sottoposto a escape con il carattere di inserimento ^
, sulla riga comandi FOR per essere interpretato come un carattere letterale quando l'interprete dei comandi di Windows elabora questa riga comandi prima di eseguire il comando FOR che esegue la dir
riga comandi incorporata in un processo di comando separato avviato sullo sfondo.
FOR elabora l'output acquisito scritto per gestire STDOUT di un processo di comando avviato che sono i nomi delle sottodirectory senza percorso e mai racchiuse tra virgolette doppie.
FOR con opzione /F
ignora le righe vuote che non si verificano qui poiché DIR con l'opzione /B
non genera righe vuote.
FOR ignorerebbe anche le righe che iniziano con un punto e virgola che è il carattere di fine riga predefinito. Un nome di directory può iniziare con un punto e virgola. Per questo motivo eol=|
viene utilizzato per definire il carattere della barra verticale come carattere di fine riga che nessuna directory o file può avere nel suo nome.
FOR dividerebbe la linea in sottostringhe usando lo spazio e la scheda orizzontale come delimitatori e assegnerebbe solo la prima stringa delimitata da spazio / scheda alla variabile loop specificata I
. Questo comportamento di divisione non è desiderato qui perché un nome di directory può contenere uno o più spazi. Pertanto delims=
viene utilizzato per definire un elenco vuoto di delimitatori per disabilitare il comportamento di divisione delle linee e ottenere assegnato alla variabile loop I
, sempre il nome completo della directory.
Il comando FOR esegue il comando RD per ciascun nome di directory senza un percorso, motivo per cui sulla riga di comando RD è necessario specificare nuovamente il percorso della cartella, che è concatenato con il nome della sottocartella.
Per comprendere i comandi utilizzati e il loro funzionamento, aprire una finestra del prompt dei comandi, eseguire lì i seguenti comandi e leggere attentamente tutte le pagine di aiuto visualizzate per ciascun comando.
del /?
dir /?
echo /?
endlocal /?
for /?
goto /?
if /?
rd /?
rem /?
set /?
setlocal /?