Я предлагаю этот код:
@echo off
set "BackUpDir=%~d0\BackUpDir"
for /F "skip=1" %%I in ('%SystemRoot%\System32\wbem\wmic.exe LOGICALDISK where DriveType^=3 GET DeviceID') do (
if /I not "%~d0" == "%%I" %SystemRoot%\System32\robocopy.exe %%I\ %BackUpDir% *.jpg *.jpeg *.dng *.nef *.mp4 *.mov *.wmv *.avi *.3gp *.3g2 /MIN:20000 /MAX:2703622144 /s /W:15 /XD C:\$WINDOWS.~BT "C:\System Volume Information" C:\Windows "C:\Program Files" C:\Boot C:\MSOCache C:\Recovery "C:\Program Files (x86)" "C:\Documents and Settings" C:\ProgramData "C:\Users\All Users" C:\Users\Default "C:\Users\Default User" C:\Users\defaultuser0 C:\Users\Public
)
Команда инструментария управления Windows WMIC используется для доступа к информации Win32_LogicalDisk class . Представляет интерес буква диска с двоеточием, хранящаяся в свойстве DeviceID
.
Все подключенные в настоящий момент логические диски будут выводиться с командной строкой:
%SystemRoot%\System32\wbem\wmic.exe LOGICALDISK GET DeviceID
Например, вывод:
DeviceID
C:
D:
E:
F:
Q:
R:
S:
Существует строка заголовка с DeviceID
и следующая строка на логический диск. Все строки имеют завершающие пробелы. Выходной текст имеет кодировку UTF-16 Little Endian (два байта на символ), а не кодированный ANSI (один байт на символ).
Но интересными для задачи резервного копирования являются только локальные диски . По этой причине командная строка изменяется на:
%SystemRoot%\System32\wbem\wmic.exe LOGICALDISK GET DeviceID,DriveType
Вывод в кодировке Unicode с конечными пробелами теперь, например:
DeviceID DriveType
C: 3
D: 3
E: 3
F: 3
Q: 5
R: 5
S: 2
Хорошо, буквы диска выводятся с информацией о типе диска. Диски типа 3
представляют интерес для операции резервного копирования в соответствии с документацией Microsoft для Win32_LogicalDisk класса.
Было бы возможно отфильтровать строки в цикле FOR , используя условие IF . Но wmic.exe
предлагает также возможность фильтрации с использованием where
. Таким образом, можно напрямую отфильтровать список дисков по wmic.exe
с помощью командной строки:
%SystemRoot%\System32\wbem\wmic.exe LOGICALDISK where DriveType=3 GET DeviceID
UTF-16 LE закодированный выход с конечными пробелами, например:
DeviceID
C:
D:
E:
F:
Это вывод для обработки с помощью цикла FOR , как это сделано с помощью кода пакетного файла выше.
FOR с параметром /F
запускает в этом случае новый командный процесс в фоновом режиме с %ComSpec% /c
и командной строкой между двумя '
внутри круглых скобок, в результате чего Windows установлена в C:\Windows
при выполнении:
C:\Windows\System32\cmd.exe /c C:\Windows\System32\wbem\wmic.exe LOGICALDISK where DriveType=3 GET DeviceID
Знак равенства =
не является частью строки аргумента, заключенной в двойные кавычки. Поэтому cmd.exe
, обрабатывающий пакетный файл, интерпретирует символ =
как разделитель аргументов, такой как пробел, табуляцию или запятую, и заменяет =
на пробел перед выполнением команды FOR . Таким образом, командная строка, выполняемая отдельным командным процессом, запущенным в фоновом режиме, будет с where DriveType 3
вместо where DriveType=3
, и это будет неверный синтаксис для предложения where
. По этой причине знак равенства должен быть экранирован с ^
, чтобы интерпретироваться как литеральный символ при разборе всей командной строки FOR с ее блоком команд на cmd.exe
перед выполнением команды FOR .
FOR захватывает все выходные данные для обработки STDOUT запущенного командного процесса и обрабатывает захваченный текст построчно после того, как запущенный cmd.exe
завершил себя.
FOR игнорирует всегда пустые строки при обработке захваченного вывода.
FOR по умолчанию разделяет каждую строку на подстроки, используя в качестве разделителей обычный пробел и горизонтальную табуляцию, и назначает только первую строку с пробелом / табуляцией с разделением для указанной переменной цикла I
. Это именно то, что нужно для обработки строки.
FOR по умолчанию игнорирует также все строки, начинающиеся с точки с запятой, поскольку eol=;
является параметром по умолчанию для конца строки. Параметр конца строки не должен изменяться здесь, потому что все обрабатываемые строки начинаются с буквы диска.
В действительности FOR сначала разбивает строку, используя заданные разделители или разделители строк по умолчанию, а затем проверяет, начинается ли первая подстрока с указанного или символа конца строки по умолчанию. Так что FOR также будет игнорировать в этом случае строку, начинающуюся, например, с одного или нескольких начальных пробелов / табуляций, а следующий символ - ;
. Но это не происходит здесь, и поэтому опция конца строки по умолчанию FOR может быть сохранена.
Но первая строка вывода с DeviceID
не представляет интереса. Эта строка может быть пропущена при обработке захваченного вывода с помощью FOR с помощью опции skip=1
, заключенной в "
.
Дополнительное условие if /I not "%~d0" == "%%I"
, скорее всего, на самом деле не обязательно, если резервный диск является съемным диском с типом диска 2
.Но он позволяет использовать этот код также для резервного копирования всех локальных дисков, кроме резервного, на резервный диск, который также является локальным.