Отправлено 11 янв. 2016 г., 08:11 пользователем Anton Derbenev
[
обновлено 30 нояб. 2017 г., 08:12
]
У меня есть подозрение, что в недрах Microsoft есть специальная команда разработчиков, которая специально заботится, чтобы у всего, что связано с командной строкой Windows, были грабли, подводные камни и проблемы.
Примеры: %comspec% (cmd.exe ) требует, чтобы все параметры после /C или /K были в кавычках. Наример, нельзя выполнить cmd.exe /C "%ProgramFiles%\notepad2\notepad2.exe" "%USERPROFILE%\Documents\test.txt" , надо
cmd.exe /C ""%ProgramFiles%\notepad2\notepad2.exe" "%USERPROFILE%\Documents\test.txt""
Что ещё хуже – cmd.exe маскирует этот косяк, и там, где "замечает" свой вызов, сам подставляет внешние кавычки (причём не всегда угадывает). Но остальные программы про это не в курсе! Например, это очень сильно мешает при использовании планировщика Windows.START "notepad.exe" – не работает. Работает
START "" "notepad.exe" "%windir%\System32\find.exe" /n "4" "test.txt" отдельно – работает.
FOR /F "usebackq tokens=*" %%A IN (`"%windir%\System32\find.exe" /n "4" "test.txt"`) DO ECHO %%A – не работает. Работает
FOR /F "usebackq tokens=*" %%A IN (`%windir%\System32\find.exe /n "4" "test.txt"`) DO ECHO %%A ECHO 123>test.txt – не работает.
ECHO "123">test.txt – записывает "123" с кавычками.
ECHO 123 >test.txt – с пробелом. Чтобы заработало без пробела, надо писать
ECHO 12^3>test.txt или (ECHO 123)>test.txt ECHO – выводит ECHO is on. или локализованную фразу (по русски – четыре длинных слова). Чтобы вывести пустую строку, надо писать
ECHO. (с точкой слитно; также работает ECHO\ , ECHO] и т.п.)- Если внутри блока
( … ) будет комментарий со скобками, например, rem (проверка) , интерпретатор командной строки прочтёт закрывающую скобку как конец блока. FOR %%A in ("C:\test.file") DO ECHO %%A выводит C:\test.file независимо от наличия там test.file .- Некоторые команды не меняют код ошибки
ERRORLEVEL при вызове с неправильными параметрами командной строки. Самые назойливые примеры: NET SHARE (при этом NET USER – меняет)defrag.exe (на Win8 и выше его стоит запускать с ключом /O , на 7 этот ключ не поддерживается)
- До Windows Vista не было предустановленной переменной среды, в которой было бы указано расположение
%USERPROFILE%\Local Settings\Application Data . В Vista добавили %LOCALAPPDATA% , но ещё добавили папку %USERPROFILE%\AppData\LocalLow , расположение которой снова не указано ни в какой переменной среды. - Узнать hostname – нетривиальная задача. Есть переменная
%COMPUTERNAME% , но там всегда в верхнем регистре и обрезано, если для NetBIOS оно "слишком длинное". Впрочем, его можно прочитать из реестра, только… - При чтении ключей с помощью
reg.exe проблемы начинаются, если в названии ключа есть пробелы, поскольку reg.exe никогда не выводит на экран только значение – оно выводится всегда после названия ключа и типа значения. Так что, чтобы, например, прочитать hostname, надо писать
FOR /F "usebackq tokens= 2 *" %%I IN (`REG QUERY "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" /v "Hostname"`) DO SET "Hostname=%%~J"
но чтобы прочитать NV Hostname, надо писать уже
FOR /F "usebackq tokens= 3 *" %%I IN (`REG QUERY "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" /v "NV Hostname"`) DO SET "NVHostname=%%~J"
Интересно, что reg.exe был уже в XP (в NT4 и 2000 он был в Resource Kit). Но XP'шная команда в выводе REG QUERY разделяет поля tab'ом (символ с кодом 8). Поскольку в названиях ключей tab'ов не бывает, такой вывод намного проще парсить (однако, от шапки всё равно никак не избавиться). Примерно так:
FOR /F "usebackq tokens= 2 * delims= <tab> " %%I IN (`REG QUERY "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" /v "Hostname"`) DO SET "Hostname=%%~J" указанный жирным курсивом <tab> должен быть в тексте пакетного файла в виде одного символа с кодом 8, а не в виде треугольных скобок и букв. В таком случае число после tokens= не зависит от количества пробелов в названии ключа. Кстати, если читаете путь из реестра, молитесь, чтобы там не было международных символов. Обнаружить их в командной строке – нереально, а выдаются reg'ом они в кодировке ANSI (напоминаю, cmd.exe работает в OEM), поэтому при наличии не-ASCII символов, при попытке совершить chdir (или что угодно другое) пакетный файл будет поджидать облом. - Копирование папок – эпичный пример фейла (или win'а команды из первого абзаца?). Типичная команда для копирования папки в Windows:
xcopy s:\WindowsImageBackup r:\WindowsImageBackup /E /I /Q /G /H /R /K /O /Y /B /J смогли с первого раза посчитать количество ключей? Ну ок, наверное, не все они требуются. Вот необходимый минимум, чтобы xcopy не остановился где-нибудь посередине и не задал тупой вопрос, ожидая интерактивного ответа: /E /I /G /H /R /Y . Да, кстати, Вы использовали copy ? Облом будет поджидать Вас незаметно :) Ключи copy указываются перед аргументами откуда и куда, xcopy – после аргументов. %comspec% /U /C "ECHO 123>test.txt" записывает файл в UNICODE.
%comspec% /U /C "FOR /F %A IN (test.txt) DO ECHO %A" не может прочитать его!
|
|