Как выбрать доступные диски, кроме Pendrive для резервного копирования? - PullRequest
1 голос
/ 09 июня 2019

Я сделал этот сценарий для своих домашних компьютеров, чтобы легко создавать резервные копии всей моей коллекции фотографий и видео на один внешний жесткий диск.

SET BackUpDir=%~d0\BackUpDir

for %%d in (C:\ D:\) do (
    if exist %%d (
    robocopy %%d %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 )
)
exit 0

У меня есть несколько компьютеров с различными структурами разделов. Один из них имеет только диски C: и D:, но, например, второй имеет пять разделов.

Теперь у меня есть эта строка кода с поиском файлов только на двух разделах:

for %%d in (C:\ D:\) do (

Я не хочу каждый раз редактировать скрипт, чтобы добавить дополнительные разделы, которые не существуют, например, на первом компьютере, но существуют на втором компьютере. Я хочу, чтобы мой сценарий автоматически находил все доступные разделы на компьютере, кроме внешнего жесткого диска, с которого выполняется сценарий резервного копирования.

Как изменить командную строку выше, чтобы это произошло?

Я хочу что-то вроде этого:

for %%d in ("list of all partition" except "backup external hard drive") do (

Ответы [ 2 ]

1 голос
/ 09 июня 2019

Я предлагаю этот код:

@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.Но он позволяет использовать этот код также для резервного копирования всех локальных дисков, кроме резервного, на резервный диск, который также является локальным.

1 голос
/ 09 июня 2019

Вы уже знаете , как получить диск, который вы хотите исключить, он находится в первой строке, %~d0, так как вы используете его для установки каталога, в который вы хотите создать резервную копию.

Кроме того, вы можете использовать exist, чтобы узнать, какие диски действительно существуют.

Таким образом, следующий скрипт будет обрабатывать все существующие диски, которые не соответствуют тому, где находится ваш скрипт.работает с:

@echo off
rem Expand following list as needed.
for %%d in (C D E F G H I J) do (
    if exist %%d:\. if not %%d:==%~d0 (
        echo Processing drive %%d
    )
)

Когда я запускаю его с диска C: в моей системе, которая имеет диск C:, пустой диск D: DVD и SSD E:, я получаю:

Processing drive E
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...