Я импортирую переменные из config.txt
в свой .bat
файл.
Ниже приводится содержание моего config.txt
:
param1 = %LOCALAPPDATA%\Programs
param2 = %LOCALAPPDATA%\Programs\Myfolder
Это содержимое моего .bat
файла:
for /f "delims = " %%L in (config.txt) do set %%L
echo %param1%
Это выводит:
%LOCALAPPDATA%\Programs
Но я хочу, чтобы он вывел:
C:\Users\Alaska\AppData\Local\Programs
Если вы хотите еще один раунд расширения переменных, используйте команду call
.
Если вам нужно, чтобы переменная содержала %LOCALAPPDATA%
, используйте ее перед командой echo
:
for /f "delims = " %%L in (config.txt) do set %%L
call echo %param1%
Если вы хотите, чтобы переменная была расширена до полного значения, используйте ее перед командой set
:
for /f "delims = " %%L in (config.txt) do call set %%L
echo %param1%
Типовые решения уже опубликованы SomethingDark. Это работает в большинстве случаев.
Но у этого решения есть лишь некоторые недостатки.
call
приводит к еще одному синтаксическому анализу командной строки, которая отвечает за расширение %VariableName%
соответствующим значением ссылочной переменной среды. Но если строка файла/папки также содержит один или несколько символов %
, которые являются частью имени папки/файла, а не ссылкой на переменную среды, знак процента (единственное или последнее появление) или все, что находится между двумя знаками процента, удаляется из строки. в результате получается неверная строка файла/папки.call
приводит к тому, что cmd.exe
ищет файл с именем, указанным следующим, например set
или echo
, в текущем каталоге и далее во всех каталогах локальной переменной среды PATH
с расширением файла, указанным в локальной переменной среды PATHEXT
. Если файл с таким именем и соответствующим расширением действительно случайно найден, файл выполняется вместо внутренней команды cmd
set
или echo
.&
являлся частью строки файла/папки.Предположим, что каталог C:\Temp\Batch Test
содержит файл config.txt
со следующими строками:
param1=%LOCALAPPDATA%\Test1
param2=%TEMP%\Development & Test 100% (!)\Test2
param3 = "%TEMP%\Development & Test 100% (!) and really 100%\Test3"
param4=..\Data\Test4
В этом каталоге находится командный файл Test1.cmd
со строками:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /f "delims = " %%L in (config.txt) do set %%L
set param
if defined param1 call echo %param1%
if defined param2 call echo %param2%
if defined param3 call echo %param3%
if defined param4 call echo %param4%
endlocal
Запуск пакетного файла Test1.cmd
с текущим каталогом C:\Temp\Batch Test
без файла с именем echo
, найденного в текущем каталоге или в каталогах переменной среды PATH
с расширением файла, указанным в переменной среды PATHEXT
, приводит к выводу:
param1=%LOCALAPPDATA%\Test1
param2=%TEMP%\Development & Test 100% (!)\Test2
param3 = "%TEMP%\Development & Test 100% (!) and really 100%\Test3"
param4=..\Data\Test4
C:\Users\username\AppData\Local\Test1
C:\Users\username\AppData\Local\Temp\Development
'Test' is not recognized as an internal or external command,
operable program or batch file.
"C:\Users\username\AppData\Local\Temp\Development & Test 100\Test3"
..\Data\Test4
Проблемы следующие:
param2
неверен и приводит к интерпретации Test
после &
как дополнительной команды для запуска после echo
, которая выводит только C:\Users\username\AppData\Local\Temp\Development
. Строка param2
не заключена в "
внутри config.txt
, и командный файл не распознает это и не обрабатывает строку соответствующим образом.% (!) and really 100%
в строке param3
интерпретируется как ссылка на переменную среды с именем (!) and really 100
. Такой переменной среды нет, и поэтому эта часть имени папки ошибочно заменяется пустой строкой.param3
находится в окружении "
и по этой причине работает, несмотря на &
в строковом значении. Но для дальнейшей обработки пакетного файла нехорошо, если строки, назначенные переменным среды от param1
до param4
, могут быть без двойных кавычек или с ними.param4
по-прежнему содержит относительный путь к родительскому каталогу текущего рабочего каталога, что может быть как хорошо, так и плохо в зависимости от того, какой каталог установлен родительским процессом в качестве текущего рабочего при запуске cmd.exe
для обработки пакетного файла и в зависимости от Пакетный файл предназначен для запуска с текущим каталогом или с каталогом пакетного файла.Каталог C:\Temp\Batch Test
также содержит командный файл с именем Test2.cmd
со следующими строками:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /f "delims = " %%L in (config.txt) do call set %%L
set param
endlocal
Запуск пакетного файла Test2.cmd
с текущим каталогом C:\Temp\Batch Test
без файла с именем set
, найденного в текущем каталоге или в каталогах переменной среды PATH
с расширением файла, указанным в переменной среды PATHEXT
, приводит к выводу:
param1=C:\Users\username\AppData\Local\Test1
param3 = "C:\Users\username\AppData\Local\Temp\Development & Test 100\Test3"
param4=..\Data\Test4
Проблемы следующие:
param2
вообще не определена.param3
содержит строку файла/папки, заключенную в "
, в то время как две другие переменные не имеют окружения "
, что может вызвать проблемы при дальнейшей обработке пакетного файла.% (!) and really 100%
интерпретируется как ссылка на переменную среды с именем (!) and really 100
. Такой переменной среды нет, и поэтому эта часть имени папки ошибочно заменяется пустой строкой.param4
по-прежнему содержит относительный путь к родительскому каталогу текущего рабочего каталога, что может быть как хорошо, так и плохо в зависимости от того, какой каталог установлен родительским процессом в качестве текущего рабочего при запуске cmd.exe
для обработки пакетного файла и в зависимости от Пакетный файл предназначен для запуска с текущим каталогом или с каталогом пакетного файла.Все эти недостатки и проблемы не возникают при использовании следующего командного файла Test3.cmd
, также хранящегося в каталоге C:\Temp\Batch Test
:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
pushd "%~dp0" || exit /B 1
for /f "usebackq tokens=1* delims= = " %%G in ("%~dp0config.txt") do for /F delims^=^ eol^= %%I in ('echo "%%~H"') do set "%%G=%%~fI"
set param
popd
endlocal
Этот пакетный файл выполняется с помощью "C:\Temp\Batch Test\Test3.cmd"
, при этом текущий каталог C:\Users\username
является типичным при открытии окна командной строки. Результат:
param1=C:\Users\username\AppData\Local\Test1
param2=C:\Users\username\AppData\Local\Temp\Development & Test 100% (!)\Test2
param3=C:\Users\username\AppData\Local\Temp\Development & Test 100% (!) and really 100%\Test3
param4=C:\Temp\Data\Test4
Третью командную строку можно удалить, если пакетный файл должен использовать текущий рабочий каталог, определенный вне командного файла. Эта строка гарантирует, что текущий рабочий каталог во время выполнения пакетного файла является каталогом, содержащим пакетный файл, который важен для param4
.
Преимущества заключаются в следующем:
call
для расширения ссылок на переменные среды в строках файлов/папок в текстовом файле config.txt
. Командный процессор Windows никогда не ищет файл с именем set
или echo
в текущем рабочем каталоге или в любом каталоге, указанном в переменной среды PATH
, с расширением файла, указанным в переменной среды PATHEXT
.%
в строке файла/папки, являющийся частью имени файла/папки, сохраняется даже при расширении ссылок на переменные среды, используемых в той же строке."
, даже если config.txt
содержат строки без двойных кавычек и с двойными кавычками. На строки файла/папки, назначенные четырем переменным среды, теперь всегда можно ссылаться, используя окружение "
, как это требуется для строк аргументов файла/папки неизвестной консистенции.param4
с относительным путем, уже расширена до полного имени файла/папки, что полезно, если при дальнейшей обработке возникает ошибка, и строка файла/папки, назначенная param4
, выводится в сообщении об ошибке. В этом случае пользователь получает четкую информацию, какой файл/папка вызывает проблемы.Не имеет значения, существуют ли файлы/папки, на которые ссылаются, при выполнении пакетного файла, или они еще не существуют и должны быть созданы следующим пакетным файлом.
Недостатком третьего решения является немного большее время выполнения, поскольку для каждой строки в config.txt
в фоновом режиме выполняется еще один командный процесс с %ComSpec
и опцией /c
и командная строка, указанная во второй команде FOR внутри '
с командой echo
.
Однако четвертую командную строку в третьем пакетном файле следует использовать, если пакетный файл предназначен для общего использования. За почти 30 лет я действительно видел все в строке, на которую ссылается %USERNAME%
, которая является частью других предопределенных переменных среды, таких как USERPROFILE
, APPDATA
или LOCALAPPDATA
. Пользователь может определить имя учетной записи, используя все символы, разрешенные в имени файла/папки. По этой причине необходимо написать сценарий для исправления обработки каждой возможной строки имени файла/папки.