Không có câu trả lời nào được đăng vào ngày 2018-06-01, ngoại trừ dòng lệnh duy nhất được đăng bởi foxidrive , thực sự đã xóa tất cả các tệp và tất cả các thư mục / thư mục trong %PathToFolder%
. Đó là lý do để đăng thêm một câu trả lời với một dòng lệnh đơn giản để xóa tất cả các tệp và thư mục con của thư mục cũng như một tệp bó với một giải pháp phức tạp hơn giải thích lý do tại sao tất cả các câu trả lời khác được đăng vào 2018-06-01 bằng DEL và FOR với RD không thể dọn sạch hoàn toàn một thư mục.
Giải pháp dòng lệnh đơn giản mà tất nhiên cũng có thể được sử dụng trong một tệp bó:
pushd "%PathToFolder%" 2>nul && ( rd /Q /S "%PathToFolder%" 2>nul & popd )
Dòng lệnh này chứa ba lệnh được thực thi lần lượt.
Lệnh đầu tiên PUSHD đẩy đường dẫn thư mục hiện tại trên stack và tiếp theo tạo %PathToFolder%
thư mục hiện tại để chạy tiến trình lệnh.
Điều này cũng hoạt động cho các đường dẫn UNC theo mặc định vì các phần mở rộng lệnh được bật theo mặc định và trong trường hợp này PUSHD tạo một ký tự ổ đĩa tạm thời trỏ đến tài nguyên mạng được chỉ định đó và sau đó thay đổi ổ đĩa và thư mục hiện tại, sử dụng ký tự ổ đĩa mới được xác định.
PUSHD xuất ra thông báo lỗi sau để xử lý STDERR nếu thư mục được chỉ định hoàn toàn không tồn tại:
Hệ thống không thể tìm đường dẫn cụ thể.
Thông báo lỗi này được loại bỏ bằng cách chuyển hướng nó 2>nul
đến thiết bị NUL .
Lệnh RD tiếp theo chỉ được thực thi nếu thay đổi thư mục hiện tại cho quy trình lệnh hiện tại thành thư mục được chỉ định thành công, tức là thư mục đã chỉ định tồn tại.
Lệnh RD với các tùy chọn /Q
và /S
loại bỏ một thư mục lặng lẽ với tất cả các thư mục con ngay cả khi thư mục được chỉ định chứa các tệp hoặc thư mục có thuộc tính ẩn hoặc với tập thuộc tính chỉ đọc. Thuộc tính hệ thống không bao giờ ngăn chặn việc xóa một tập tin hoặc thư mục.
Không bị xóa là:
Các thư mục được sử dụng làm thư mục hiện tại cho bất kỳ quá trình đang chạy. Toàn bộ cây thư mục cho một thư mục như vậy không thể bị xóa nếu một thư mục được sử dụng làm thư mục hiện tại cho bất kỳ quá trình đang chạy.
Các tệp hiện đang được mở bởi bất kỳ quy trình đang chạy nào với quyền truy cập tệp được đặt trên tệp đang mở để ngăn xóa tệp trong khi được mở bởi ứng dụng / quy trình đang chạy. Một tệp được mở như vậy cũng ngăn chặn việc xóa toàn bộ cây thư mục vào tệp đã mở.
Các tệp / thư mục mà người dùng hiện tại không có quyền (NTFS) cần thiết để xóa tệp / thư mục, điều này cũng ngăn việc xóa cây thư mục vào tệp / thư mục này.
Lý do đầu tiên để không xóa thư mục được sử dụng bởi dòng lệnh này để xóa tất cả các tệp và thư mục con của thư mục đã chỉ định, nhưng không phải chính thư mục đó. Thư mục được tạo tạm thời thư mục hiện tại để chạy quy trình lệnh ngăn chặn việc xóa chính thư mục. Tất nhiên điều này dẫn đến kết quả đầu ra của một thông báo lỗi bằng lệnh RD :
Quá trình không thể truy cập tệp vì nó đang được sử dụng bởi một quy trình khác.
Tệp là thuật ngữ sai ở đây vì trong thực tế, thư mục đang được sử dụng bởi một quy trình khác, quy trình lệnh hiện tại đã thực thi lệnh RD . Vâng, trong thực tế một thư mục là dành cho các hệ thống tập tin một tập tin đặc biệt với thuộc tính tập tin thư mục mà giải thích thông báo lỗi này. Nhưng tôi không muốn đi quá sâu vào quản lý hệ thống tập tin.
Thông báo lỗi này, giống như tất cả các thông báo lỗi khác, có thể xảy ra do ba lý do được viết ở trên, bị loại bỏ bằng cách chuyển hướng nó 2>nul
từ xử lý STDERR sang thiết bị NUL .
Lệnh thứ ba, POPD , được thực thi độc lập với giá trị thoát của lệnh RD .
POPD bật đường dẫn thư mục được đẩy bởi PUSHD từ ngăn xếp và thay đổi thư mục hiện tại để chạy quy trình lệnh vào thư mục này, tức là khôi phục thư mục hiện tại ban đầu. POPD xóa ký tự ổ đĩa tạm thời được tạo bởi PUSHD trong trường hợp đường dẫn thư mục UNC.
Lưu ý: POPD có thể âm thầm không thể khôi phục thư mục hiện tại ban đầu trong trường hợp thư mục hiện tại ban đầu là thư mục con của thư mục để xóa không còn tồn tại nữa. Trong trường hợp đặc biệt này %PathToFolder%
vẫn là thư mục hiện tại. Vì vậy, nên chạy dòng lệnh ở trên không phải từ thư mục con của %PathToFolder%
.
Một sự thật thú vị khác :
Tôi đã thử dòng lệnh cũng sử dụng đường dẫn UNC bằng cách chia sẻ thư mục cục bộ C:\Temp
với tên chia sẻ Temp
và sử dụng đường dẫn UNC \\%COMPUTERNAME%\Temp\CleanTest
được gán cho biến môi trường PathToFolder
trên Windows 7. Nếu thư mục hiện tại đang chạy dòng lệnh là thư mục con của một cục bộ được chia sẻ folder truy cập sử dụng đường dẫn UNC, ví dụ C:\Temp\CleanTest\Subfolder1
, Subfolder1
sẽ bị xóa bởi RD , và tiếp theo popd không âm thầm trong việc đưa ra C:\Temp\CleanTest\Subfolder1
một lần nữa thư mục hiện hành dẫn đến Z:\CleanTest
còn lại là thư mục hiện hành cho quá trình lệnh chạy. Vì vậy, trong trường hợp rất đặc biệt này, ký tự ổ đĩa tạm thời vẫn còn cho đến khi thư mục hiện tại được thay đổi, ví dụ như vớicd /D %SystemRoot%
đến một thư mục địa phương thực sự tồn tại. Thật không may, POPD không thoát với giá trị lớn hơn 0 nếu không khôi phục thư mục hiện tại ban đầu khiến không thể phát hiện tình trạng lỗi rất đặc biệt này bằng cách chỉ sử dụng mã thoát của POPD . Tuy nhiên, có thể cho rằng không ai từng gặp phải trường hợp lỗi rất đặc biệt này vì các đường dẫn UNC thường không được sử dụng để truy cập các tệp và thư mục cục bộ.
Để hiểu các lệnh được sử dụng tốt hơn nữa, hãy mở một cửa sổ nhắc lệnh, thực hiện các lệnh sau và đọc trợ giúp được hiển thị cho từng lệnh một cách cẩn thận.
Một dòng với nhiều lệnh sử dụng tệp bó Windows giải thích các toán tử &&
và &
được sử dụng ở đây.
Tiếp theo chúng ta hãy xem xét giải pháp tệp bó bằng lệnh DEL để xóa các tệp trong %PathToFolder%
và FOR và RD để xóa các thư mục con trong %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
Trước tiên, tệp bó đảm bảo rằng biến môi trường PathToFolder
thực sự được xác định bằng đường dẫn thư mục không có dấu ngoặc kép và không có dấu gạch chéo ngược ở cuối. Dấu gạch chéo ngược ở cuối sẽ không phải là vấn đề, nhưng dấu ngoặc kép trong đường dẫn thư mục có thể có vấn đề vì giá trị PathToFolder
được nối với các chuỗi khác trong khi thực hiện tệp bó.
Quan trọng là hai dòng:
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
Lệnh DEL được sử dụng để xóa tất cả các tệp trong thư mục được chỉ định.
- Tùy chọn
/A
là cần thiết để xử lý thực sự tất cả các tệp bao gồm các tệp có thuộc tính ẩn mà DEL sẽ bỏ qua mà không sử dụng tùy chọn /A
.
- Tùy chọn
/F
là cần thiết để buộc xóa các tệp với tập thuộc tính chỉ đọc.
- Tùy chọn
/Q
này là cần thiết để chạy một cách dễ dàng xóa nhiều tệp mà không nhắc người dùng nếu nhiều tệp thực sự bị xóa.
>nul
là cần thiết để chuyển hướng đầu ra của tên tệp được viết để xử lý STDOUT đến thiết bị NUL không thể bị xóa do tệp hiện đang được mở hoặc người dùng không có quyền xóa tệp.
2>nul
là cần thiết để chuyển hướng đầu ra thông báo lỗi cho mỗi tệp không thể xóa từ xử lý STDERR sang thiết bị NUL .
Các lệnh FOR và RD được sử dụng để loại bỏ tất cả các thư mục con trong thư mục được chỉ định. Nhưng for /D
không được sử dụng vì FOR đang bỏ qua trong trường hợp này các thư mục con với tập thuộc tính ẩn. Vì lý do đó for /F
được sử dụng để chạy dòng lệnh sau trong một quy trình lệnh riêng được bắt đầu trong nền với %ComSpec% /c
:
dir "%PathToFolder%\*" /AD /B 2>nul
DIR xuất ra ở định dạng trần vì /B
các mục nhập thư mục có thuộc tính D
, tức là tên của tất cả các thư mục con trong thư mục được chỉ định độc lập với các thuộc tính khác như thuộc tính ẩn không có đường dẫn. 2>nul
được sử dụng để chuyển hướng đầu ra thông báo lỗi bằng DIR trên không có thư mục nào được tìm thấy từ tay cầm STDERR đến thiết bị NUL .
Toán tử chuyển hướng >
phải được thoát với ký tự dấu mũ ^
, trên dòng lệnh FOR được hiểu là ký tự bằng chữ khi trình thông dịch lệnh Windows xử lý dòng lệnh này trước khi thực hiện lệnh FOR thực thi dir
dòng lệnh nhúng trong một quy trình lệnh riêng biệt bắt đầu trong nền.
FOR xử lý đầu ra bị bắt được viết để xử lý STDOUT của quy trình lệnh đã bắt đầu là tên của các thư mục con không có đường dẫn và không bao giờ được đặt trong dấu ngoặc kép.
FOR với tùy chọn /F
bỏ qua các dòng trống không xuất hiện ở đây vì DIR với tùy chọn /B
không xuất ra các dòng trống.
FOR cũng sẽ bỏ qua các dòng bắt đầu bằng dấu chấm phẩy là kết thúc mặc định của ký tự dòng. Tên thư mục có thể bắt đầu bằng dấu chấm phẩy. Vì lý do đó eol=|
được sử dụng để xác định ký tự thanh dọc là ký tự cuối dòng mà không thư mục hoặc tệp nào có thể có trong tên của nó.
FOR sẽ phân chia dòng thành các chuỗi con bằng cách sử dụng dấu cách và tab ngang làm dấu phân cách và sẽ chỉ gán chuỗi phân tách không gian / tab đầu tiên cho biến vòng lặp được chỉ định I
. Hành vi chia tách này không muốn ở đây vì tên thư mục có thể chứa một hoặc nhiều khoảng trắng. Do đó, delims=
được sử dụng để xác định một danh sách trống các dấu phân cách để vô hiệu hóa hành vi phân tách dòng và được gán cho biến vòng lặp I
, luôn luôn là tên thư mục đầy đủ.
Lệnh FOR chạy lệnh RD cho mỗi tên thư mục mà không có đường dẫn, đó là lý do tại sao trên dòng lệnh RD , đường dẫn thư mục phải được chỉ định một lần nữa được nối với tên thư mục con.
Để hiểu các lệnh được sử dụng và cách chúng hoạt động, hãy mở một cửa sổ nhắc lệnh, thực hiện các lệnh sau và đọc toàn bộ các trang trợ giúp được hiển thị cho mỗi lệnh rất cẩn thận.
del /?
dir /?
echo /?
endlocal /?
for /?
goto /?
if /?
rd /?
rem /?
set /?
setlocal /?