Мое решение использует в пакетном файле:
@echo off
for /F "tokens=3 delims=/=" %%I in ('%SystemRoot%\System32\findstr.exe /I /L "src" VirtualBox.xml') do set "VirtualBoxPath=%%~dpI"
echo Virtual box path is: "%VirtualBoxPath%"
FOR с параметром /F
, в этом случае запускается новый командный процесс в фоновом режиме с %ComSpec% /c
и командной строкоймежду двумя '
внутри круглых скобок, в результате чего Windows установлена в C:\Windows
при выполнении:
C:\Windows\System32\cmd.exe /c C:\Windows\System32\findstr.exe /I /L "src" VirtualBox.xml
FINDSTR поиск без учета регистра строк, содержащих буквенную строку src
в файле VirtualBox.xml
в текущем каталоге, который также может быть каталогом, отличным от каталога, содержащего пакетный файл.В этом случае FINDSTR выводит для обработки STDOUT фоновой команды, обрабатывающей строку:
<MachineEntry uuid="{awae1979-6512-4br8-acg5-3oe94f56712de}" src="C:\Users\John\VirtualBox VMs\VM\VM.vbox"/>
FOR захватывает все выходные данные для обработки STDOUT запущенного командного процесса и обрабатывает захваченный текст построчно после того, как запущенный cmd.exe
завершился сам.
FOR игнорирует всегда пустые строки при обработке захваченного вывода.
FOR по умолчанию разделяет каждую строку на подстроки, используя обычный пробел и горизонтальную табуляцию в качестве разделителей, и назначает только первую строку с пробелом / символ табуляции с разделителями для указанной переменной цикла I
.Поведение разделения строки изменено для этой задачи путем указания tokens=3 delims=/=
в FOR командной строке после опции /F
.
Разделителями строк теперь являются косая черта /
и равныезнак =
, означающий, что строка XML для обработки разбивается на:
<MachineEntry uuid
"{awae1979-6512-4br8-acg5-3oe94f56712de}" src
"C:\Users\John\VirtualBox VMs\VM\VM.vbox"
>
Интересна только третья строка, которая назначается переменной цикла I
из-за tokens=3
.
Таким образом, переменной цикла I
присваивается строка:
"C:\Users\John\VirtualBox VMs\VM\VM.vbox"
FOR по умолчанию игнорирует также все строки, начинающиеся с точки с запятой, поскольку eol=;
является значением по умолчанию для конца строки.Параметр конца строки не должен изменяться здесь, потому что обрабатываемая строка XML никогда не начинается с ;
.
В действительности FOR сначала разбивает строку, используя указанную строку или строку по умолчаниюразделители, а затем проверяет, начинается ли первая подстрока с заданным символом или символом конца строки по умолчанию.Так что FOR также будет игнорировать в этом случае строку, начинающуюся, например, с =/;
из-за =
и /
, будет удалена во время разбиения строки, а затем первая подстрока начинается с ;
, хотя строкасамо начинается с =
, и по этой причине строка полностью игнорируется, хотя назначенная переменной цикла I
должна быть третьей, а не первой подстрокой.
Ссылка на строку, назначенную переменной цикла I
с %%~dp
с использованием трех модификаторов:
- Первый -
~
, что приводит к удалению окружающего "
из строки, присвоенной переменной цикла I
. - Второйодин -
d
, что означает букву диска с двоеточием. - Третий -
p
, что означает путь без буквы диска и двоеточия.
Путь - это все до последней обратной косой черты, включая последнюю обратную косую черту..
Поэтому строка C:\Users\John\VirtualBox VMs\VM\
присваивается переменной среды VirtualBoxPath
.
В общем случае она не соответствуеттер при применении модификаторов к строке, назначенной переменной цикла, если эта строка действительно ссылается на существующий файл или папку.Модификаторы применяются к самой строке, если файл / папка не может быть найден FOR со строкой, присвоенной ссылочной переменной цикла в файловой системе.Конечно, файл / папка, на которую ссылается строка, назначенная переменной цикла, должен существовать, если он неполный, например, просто имя файла без расширения файла назначено переменной цикла и требуется диск, путь или расширение файла.В этом случае FOR получает доступ к файловой системе, чтобы получить полное имя файла с неполной строкой имени файла, и старается получить необходимые данные.