user340956 был болезненно близок к решению, но вы знаете, что говорят о close…
Для ясности, rd /s /q c:\foobar
удаляет целевую директорию в дополнение к ее содержимому, но вы не всегда хотите удалить саму директорию, иногда вы просто хотите удалить ее содержимое и оставить директорию в покое. Команда deltree
могла бы это сделать, но Micrsoft, в своей бесконечной “мудрости”, удалил эту команду и не портировал ее на Windows.
Вот решение, которое работает, не прибегая к сторонним инструментам. Скорее всего, оно максимально простое и эффективное, как это возможно с помощью командного сценария, вместо того, чтобы прямо писать реальный исполняемый файл. Он не устанавливает никаких переменных окружения и не использует никаких циклов. Он также настолько безопасен, насколько это возможно, с проверкой ошибок везде, где это возможно, а также настолько удобен, насколько это возможно, со встроенными документами
dt.bat
(или dt.cmd
для детей; неважно, я старый, я использую .bat
):
:: dt is a Windows-compatible version of the deltree command
:: Posted to SuperUser by Synetech: https://superuser.com/a/1526232/3279
@echo off
goto start
:start
if ["%~1"]==[""] goto usage
pushd "%~1" 2>nul
if /i not ["%cd%"]==["%~1"] goto wrongdir
rd /s /q "%~1" 2>nul
popd
goto :eof
:usage
echo Delete all of the contents of a directory
echo.
echo ^> %0 DIR
echo.
echo %0 is a substitute for deltree, it recursively deletes the contents
echo (files and folders) of a directory, but not the directory itself
echo.
echo DIR is the directory whose contents are to be deleted
goto :eof
:wrongdir
echo Could not change to the target directory. Invalid directory? Access denied?
goto :eof
Вот как это работает:
- Он проверяет, был ли передан аргумент командной строки, и печатает информацию об использовании, и выходит, если нет.
- Она использует
pushd
для сохранения текущей директории, затем переключается на целевую директорию, перенаправляя любые ошибки на nul
для более чистого использования командной строки (и более чистого ведения логов).
- Он проверяет, не совпадает ли текущий каталог с целевым, печатает сообщение об ошибке и выходит, если это не так. Это позволяет избежать случайного удаления содержимого предыдущего каталога, если команда
pushd
не сработала (например, передача недействительной директории, доступ-ошибка и т.д.)
- Эта проверка не чувствительна к регистру, поэтому она обычно безопасна в Windows, но не для любых чувствительных к регистру файловых систем, подобных тем, что используются в системах *nix, даже в Windows.
- Она не работает с короткими именами (например,
C:\Users\Bob Bobson\foobar
не будет восприниматься как то же самое, что C:\Users\BobBob~1\foobar
, даже если они на самом деле таковыми являются). Немного неудобно использовать не короткое имя файла, но это лучше безопасно, чем извиняться, тем более, что SFN не полностью надежны или не всегда предсказуемы (и даже могут быть отключены вообще).
- 4. Затем она использует
rd
для удаления целевого каталога и всего его содержимого, перенаправляя любые ошибки (которые должны быть, по крайней мере, одна для самого каталога) на nul
. Некоторые заметки об этом:
- Так как целевой каталог - это текущий каталог, то система имеет к нему открытый файл-хэндл, и, таким образом, она не может фактически удалить его, поэтому он остается как есть, что и является желаемым поведением.
- Так как она не пытается удалить целевой каталог до тех пор, пока его содержимое не будет удалено, теперь он должен быть пустым (кроме всего, что также имеет открытые файловые хэндлы).
- Наконец, она использует
popd
для возврата в предыдущий каталог и заканчивает работу скрипта.
(При желании, вы можете прокомментировать скрипт с приведенными выше описаниями, используя rem
или ::
).