Это не невозможно сделать с помощью пакетного скрипта. Однако самый простой способ - использовать RoboCopy
. К сожалению, это включено только в Vista и более поздних версиях, но пользователи XP могут установить этот набор ресурсов или получить автономную копию в другом месте.
robocopy <source> <destination> /mir
Из справки (robocopy /?
):
/E :: copy subdirectories, including Empty ones.
/PURGE :: delete dest files/dirs that no longer exist in source.
/MIR :: MIRror a directory tree (equivalent to /E plus /PURGE).
К сожалению, если вы не можете запустить внешние исполняемые файлы, потребуется пакетный скрипт.
Редактировать:
В целях полноты я написал этот пакетный скрипт. Просто обязательно проверь в безопасном месте кулак, хотя, похоже, сработает. Возможно, вы захотите удалить (или прокомментировать, передвинуть rem
перед) строки del
и rmdir
для тестирования.
@echo off
setlocal EnableDelayedExpansion
set dirsrc=%~f1
set dirdest=%~f2
echo Source: "%dirsrc%"
echo Destination: "%dirdest%"
echo.
echo.
echo Cleaning files...
for /f "tokens=*" %%a in ('dir /s /b /a:-d "%dirdest%"') do (
set curdest=%%a
set cursrc=!curdest:%dirdest%=%dirsrc%!
if not exist !cursrc! (
echo Deleting "!curdest!"
del "!curdest!"
)
)
echo.
echo.
echo Cleaning directories...
set NLM=^
set NL=^^^%NLM%%NLM%^%NLM%%NLM%
rem Two lines left empty for NewLine to work
for /f "tokens=*" %%a in ('dir /s /b /a:d "%dirdest%"') do (
set curdest=%%a
set cursrc=!curdest:%dirdest%=%dirsrc%!
if not exist !cursrc! (
set rmlist=!curdest!?!rmlist!
)
)
set rmlist=!rmlist:?=%NL%!
for /f "tokens=*" %%a in ("!rmlist!") do (
if exist %%a (
echo Removing directory "%%a"
rmdir "%%a"
)
)
endlocal
Использование довольно просто: сохраните как файл .bat (например, purge.bat) и назовите его так: purge source destination
. Если у вас есть пробелы в исходных или целевых путях, вам придется добавлять кавычки, как и в любой другой командной строке ... команда.
Я кратко объясню.
Во-первых, файлы удаляются. Он выполняет замену строки, заменяя путь назначения на путь источника, поэтому он может проверить, существует ли файл в источнике. Это позволяет мне сообщать, какие файлы удаляются, и когда я приступаю к удалению каталогов, они гарантированно не содержат файлов. Это позволяет мне избежать уродства rmdir /s
, который удаляет все подкаталоги и файлы, так же как и rm -r
в Linux. Кроме того, различие между файлом и каталогом только по пути в пакете является довольно запутанным.
Когда я удаляю каталоги, я строю строку в обратном порядке, содержащую все пути к каталогам. Это так, что самый глубокий уровень удаляется первым, потому что dir /s
всегда обеспечивает самые глубокие уровни последними. Это, однако, вероятно, будет в обратном алфавитном порядке.
Кроме того, спасибо за сценарий bash Eroen, но я не могу читать bash;)