('findstr / b URL =% ~ 1') не работает с ö, ä, ü в пути или имени файла

Я хочу найти "URL =" в файле. Поскольку я новичок в таких вещах, я собрал несколько фрагментов кода из stackoverflow, ... ;-)

http://www.dostips.com/forum/viewtopic.php?f=3&t=2836&start=30

Получить список переданных аргументов в пакетном скрипте Windows (.bat )

Как получить даже самые странные параметры командной строки?

моя проблема: если файл или путь содержит немецкий "ö / ä / ü" или буквы / знаки из иностранных языков в пути или имени файла

D:\...\fähren

рассматривается как это

D:\...\f"hren

и findstr сообщает "не могу открыть файл". Вот часть моего .bat

rem %cmdcmdline%
...
:file   rem url from .url file  - im file steht URL=http.... .htm
for /f "delims=" %%a in ('findstr /b "URL=" "%~1"') do set URL="%%a"
echo. %URL% | FIND /I "URL=">Nul || (set URL=""&goto startit)

rem delete all until URL
set URL="%URL:*URL=%
rem delete =
set URL="%URL:~2%

.bat вызывается из окон, как это

HKEY_CLASSES_ROOT\InternetShortcut\shell\chrome\command "D:\sources\chrome\portable\chrome\chrome.exe" "%1"

rem% cmdcmdline% в начале .bat выглядит нормально

D:\4all\reisen\istanbul\verkehr\fähren>rem C:\Windows\system32\cmd.exe /c ""C:\Users\gigoelri\AppData\Local\Temp\333A.tmp\chrome_pause.bat" D:\sources\chrome\portable\chrome\chrome.exe D:\4all\reisen\istanbul\verkehr\fähren\Bosp_eminönü_2h_14h30_12tl_SehirHatlari.url "

вывод цикла for выглядит так:

D:\4all\reisen\istanbul\verkehr\fähren>for /F "delims=" %a in ('findstr /b "URL=" "D:\4all\reisen\istanbul\verkehr\fähren\Bosp_eminönü_2h_14h30_12tl_SehirHatlari.url"') do set URL="%a"
FINDSTR: D:\4all\reisen\istanbul\verkehr\f"hren\Bosp_emin"n?_2h_14h30_12tl_SehirHatlari.url kann nicht geöffnet werden.(cannot be opened)

D:\4all\reisen\istanbul\verkehr\fähren>echo.    | FIND /I "URL="  1>Nul  || (set URL=""  & goto startit )

Кодовая страница моего окна cmd:

D:\sources\firefox\_install>chcp
Aktive Codepage: 850.

Mofi 4: пробуем метод mofis 4 - результат: файл не найден

rem C:\Windows\system32\cmd.exe /c ""C:\Users\gigoelri\AppData\Local\Temp\F54D.tmp\firefox_pause.bat" D:\sources\firefox\portable\firefox\firefox.exe D:\4all\reisen\istanbul\verkehr\fähren\Bosp_eminönü_2h_14h30_12tl_SehirHatlari.url "
...
D:\4all\reisen\istanbul\verkehr\fähren>for /F "usebackq tokens=1* delims==" %a in ("D:\4all\reisen\istanbul\verkehr\fähren\Bosp_eminönü_2h_14h30_12tl_SehirHatlari.url") do (if /I "%a" == "URL" (
set "URL=%b"
 goto startit
) )
Die Datei "D:\4all\reisen\istanbul\verkehr\fähren\Bosp_eminönü_2h_14h30_12tl_SehirHatlari.url" 
kann nicht gefunden werden.

На этот раз причина в том, что имя файла содержит турецкие буквы, такие как "Ş" вместо "S"

Изменить 20150629:

Система - Windows7, а диск D: NTFS.

% ~ s1 тоже не работает:

D:\4all\reisen\istanbul\verkehr\fähren>for /F "usebackq tokens=1* delims==" %a in ("D:\4all\reisen\istanbul\verkehr\FHREN~1\Bosp_eminönü_2h_14h30_12tl_SehirHatlari.url") do (if /I "%a" == "URL" (
set "URL=%b"
 goto startit
) )
Die Datei "D:\4all\reisen\istanbul\verkehr\FHREN~1\Bosp_eminönü_2h_14h30_12tl_SehirHatlari.url" kann nicht gefunden werden.

Имя файла проводника: Bosp_eminönü_2h_14h30_12tl_ Ş ehirHatlar ı .url Файл URL был создан путем перетаскивания следующего URL из chrome http://en.sehirhatlari.com.tr/en/timetable/short-bosphorus-tour-363.html

Команда% windir% \ system32 \ cmd.exe dir показывает: ни Ş, ни ı в конце не отображаются В ПОРЯДКЕ.

И похоже, что .exe вызывается уже с неправильным именем:

Изменить 20150630a:

Я скрываю .bat с помощью Bat_To_Exe_Converter_ (x64) .exe. Я делаю это, например потому что таким образом записи реестра могут быть неизменными, а .exe можно закрепить без дополнительных усилий.

И вы правы, если windows вызывает .bat, все ок.

HKEY_CLASSES_ROOT\IE.AssocFile.URL\Shell\firefox\command
"D:\sources\firefox\_install\firefox.bat" "%1"

Может ли Windows передавать параметры по-разному в зависимости от того, вызывает ли он .bat или .exe?

!!!! @Mofi: Спасибо за расширенную поддержку 1a !!!!

Это не похоже на проблему «конвертера bat в exe», потому что: Пожалуйста, обратите внимание на оператор rem в первой строке. Он немного отличается от постета скриншота .exe в разделе «Правка 20150629». Есть дополнительный оператор «C: \ Users \ gigoelri \ AppData \ Local \ Temp \ F411.tmp \ firefox_pause.bat», «» установлены по-другому, а URL пишется по-другому в конце ... ı .url "" вместо ... i .url "


person ggggg    schedule 24.06.2015    source источник
comment
попробуйте с коротким именем "%~s1"   -  person npocmaka    schedule 24.06.2015


Ответы (1)


1. О заключении в кавычки значений, присвоенных переменным

Очень распространенная ошибка заключается в использовании:

set variable="value with spaces"

Это присваивает "value with spaces" и все остальное до конца строки, например конечные пробелы, variable.

Правильное расположение первой двойной кавычки:

set "variable=value with spaces"

Это присваивает только value with spaces variable независимо от конечных пробелов или табуляции в этой строке.

Дополнительные сведения см. В моем ответе на Почему не выводится строка с 'echo% var%' после использования 'set var = text' в командной строке ?

2. Тестирование присваивания выполняется в цикле FOR.

for /f "delims=" %%a in ('findstr /b "URL=" "%~1"') do set URL="%%a"
echo. %URL% | FIND /I "URL=">Nul || (set URL=""&goto chrome)

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

Намного легче читать и быстрее выполнять:

@echo off
set "URL="
for /F "delims=" %%a in ('%SystemRoot%\System32\findstr.exe /b "URL=" "%~1" 2^>nul') do set "URL=%%a"

if "%URL%"=="" goto Chrome

rem Remove URL= from string value.
set "URL=%URL:~4%"

echo URL found: %URL%
goto :EOF

:Chrome
echo No URL found.

Удаление URL= без учета регистра теперь намного проще, поскольку двойные кавычки не являются частью строкового значения, присвоенного переменной URL из-за присвоения значения кавычки переменной справа.

3. Кодовая страница в графическом интерфейсе и в окнах консоли.

В странах Германии кодовая страница, используемая в графическом интерфейсе для строк, отличных от Unicode, - Windows-1252.

Но в окнах консоли по умолчанию в странах Германии используется OEM-кодовая страница 850.

При сравнении двух таблиц можно увидеть, что немецкие умляуты имеют разные байтовые значения на этих двух кодовых страницах, что объясняет то, что вы видите.

Кодовую страницу, используемую по умолчанию в окнах консоли, можно увидеть, открыв окно командной строки и запустив там либо команду chcp без каких-либо параметров, либо команду mode без каких-либо параметров. В обоих случаях использованная кодовая страница выводится в окне консоли.

Команда chcp означает изменить кодовую страницу и поэтому может использоваться для переключения кодовой страницы для активной командной строки.

То, что вам нужно сделать в пакетном файле, зависит от того, какая кодировка используется для строки имени файла, переданной в качестве параметра пакетному файлу.


Редактировать после того, как спрашивающий предоставил дополнительную информацию о том, как вызывается пакетный файл.

4. Метод без использования FINDSTR

findstr не требуется для этой задачи. Использование findstr просто делает командный файл медленнее и сложнее, чем необходимо.

Поэтому я предлагаю гораздо более простое пакетное решение для этой задачи:

@echo off
for /F "usebackq tokens=1* delims==" %%a in ("%~1") do (
    if /I "%%a"=="URL" (
        set "URL=%%b"
        goto FoundURL
    )
)
echo No URL found.
goto :EOF

:FoundURL
echo URL found: %URL%

Файл * .url теперь анализируется непосредственно интерпретатором командной строки с помощью for вместо использования findstr.

Чтобы получить справку по этой команде, запустите for /? в окне командной строки.

По умолчанию строка в двойных кавычках анализируется напрямую при использовании for с параметром /F. Но для этой задачи необходимо проанализировать файл, полный путь которого указан в двойных кавычках. Поэтому usebackq используется для изменения поведения для при синтаксическом анализе строки, чтобы получить имя файла с путем в двойных кавычках, интерпретируемое как имя файла для синтаксического анализа.

Далее этот командный файл интересует только строка:

URL=https://stackoverflow.com/

Таким образом, delims== используется для разделения каждой строки на строки с использованием знака равенства в качестве разделителя.

Требуется строка слева от первого знака равенства и все, что находится справа от первого знака равенства, которое, конечно, может также содержать 1 или несколько знаков равенства. Мы получаем именно такое поведение разделения с tokens=1*. Строка слева от первого знака равенства - это токен 1, который назначается переменной цикла a, а все остальное после первого знака равенства - это токен 2, который назначается переменной цикла b.

При нечувствительном к регистру сравнении строки слева до знака равенства со строкой URL выполняется проверка, найдена ли интересующая строка в файле. В этом случае токен 2, являющийся строкой URL, назначается переменной среды URL, и цикл завершается переходом к метке, поскольку нет необходимости в дальнейшем синтаксическом анализе оставшихся строк файла.

Если цикл for завершается нормально, в любом случае в файле * .url нет строки, начинающейся с URL=. Тогда результатом будет соответствующее информационное сообщение перед выходом из пакетного файла с goto :EOF (EOF - конец файла - в настоящее время всегда существует, поскольку предопределенная метка).

В противном случае найденный URL выводится перед выходом из этого демонстрационного командного файла.

Этот командный файл вызывается в окне командной строки с помощью

D:\4all\reisen\istanbul\verkehr\fähren\Bosp_eminönü_2h_14h30_12tl_SehirHatlari.url

или из проводника Windows без проблем открыть файл с немецкими умляутами и разобрать его.


Вопросник спросил:

Может ли Windows передавать параметры по-разному в зависимости от того, вызывает ли он .bat или .exe?

Это верно для имен файлов и каталогов.

"%1" в ассоциации файлов - это заполнитель для аргумента, обычно имени файла или каталога.

Теперь у Windows есть 3 возможности передать приложению имя каталога или файла:

  1. В кратком формате с использованием формата 8.3 для всех каталогов в пути и самом имени файла. 8.3 означает только до 8 символов для имени каталога / файла и только до 3 символов для расширения файла с очень ограниченным набором символов. Этот формат используется Windows, если запускаемое приложение (.com или .exe) является 16-разрядным приложением в соответствии с заголовком запускаемого приложения.

  2. В длинном формате с использованием только символов ANSI, т.е. 1 байт на символ с нулевым байтом в конце в качестве завершения. Этот формат используется Windows, если приложение является 32-битным или 64-битным приложением в соответствии с заголовком без поддержки Unicode. Имена каталогов и файлов с символом Unicode в строке преобразуются в системный языковой стандарт кодовая страница для приложений, не поддерживающих Unicode. Системный языковой стандарт для приложений, не поддерживающих Unicode, может быть установлен пользователем в настройках Windows Регион и язык.

  3. В длинном формате с использованием символов Unicode, то есть с 2 байтами на символ, если запускаемое приложение поддерживает Unicode в соответствии с его заголовком.

Строки ANSI используют массив типа char в приложениях с кодом C / C ++ для Windows, в то время как массив типа wchar_t используется для строк Unicode. Подробности для программистов C / C ++ для Windows можно найти

"%L" можно использовать вместо "%1" для ассоциации файлов в HKEY_CLASSES_ROOT в реестре Windows, если Windows должна передавать имя файла или каталога всегда в длинном формате и никогда в коротком формате приложению. Иногда это необходимо, если приложение представляет собой гибрид, например консольное приложение C / C ++, скомпилированное с помощью DJGPP, которое является 16-битным приложением, но, тем не менее, поддерживает длинные имена файлов в кодировке ANSI из-за специального кода запуска.

Но вернемся к вопросу: да, конечно, Windows передает имена файлов и каталогов по-разному пакетному файлу или исполняемому файлу в зависимости от заголовка исполняемого файла, то есть от того, какой это тип приложения и какой тип строк он поддерживает.

Похоже, что использованный конвертер bat в exe создает 64-битное консольное приложение, поддерживающее Unicode. Таким образом, это приложение должно преобразовать правильную строку Unicode в строку ANSI, используя системный языковой стандарт учетной записи пользователя при передаче имен файлов и каталогов и других аргументов команде, в конечном итоге запускающей встроенный пакетный файл. И похоже, что этот конвертер делает эту задачу преобразования Unicode в ANSI или создание командной строки для запуска командного файла не на 100% правильным.

person Mofi    schedule 24.06.2015
comment
СПАСИБО за подробный ответ! Вы знаете, что конвертер делает преобразование правильно в этом случае? - person ggggg; 06.07.2015
comment
Я никогда не использовал конвертер bat в exe. Так что я не могу помочь вам найти подходящий для вашей задачи. - person Mofi; 06.07.2015