('findstr / b“URL =”“%〜1”')无法使用路径或文件名中的ö,ä,ü

时间:2015-06-24 13:53:37

标签: batch-file for-loop findstr

我想在文件中搜索“URL =”。因为我在这些事情上非常棒,所以我从stackoverflow收集了一些代码片段,......; - )

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

Get list of passed arguments in Windows batch script (.bat)

How to receive even the strangest command line parameters?

我的疑问: 如果文件或路径包含德语“ö/ä/ü”或来自路径或文件名的外语字母/符号

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"

.bat开头的rem%cmdcmdline%看起来没问题

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 通过从chrome中拖放以下URL来创建URL文件 URL: http://en.sehirhatlari.com.tr/en/timetable/short-bosphorus-tour-363.html

%windir%\ system32 \ cmd.exe dir命令显示:  Ş和最后的ı都没有显示OK。

.exe似乎已经用错误的名称调用了:

修改20150630a:

我使用Bat_To_Exe_Converter_(x64).exe转换.bat。我这样做,例如因为这样注册表项可以保持不变,并且.exe​​可以固定而不需要额外的努力。

你是对的,如果windows调用.bat一切都好。

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

是否可以通过不同的方式传递参数,具体取决于它调用.bat或.exe?

!!!! @Mofi:感谢您的延长1a支持!!!!

这似乎不是“蝙蝠到exe转换器”的问题,因为: 请看一下第一行rem语句。它与Edit 20150629下的.exe screenshot postet有很大的不同。 还有一个附加声明“C:\ Users \ gigoelri \ AppData \ Local \ Temp \ F411.tmp \ firefox_pause.bat”,“”设置不同,最后拼写的URL不同 ... ı .url“”而不是...... .url“

1 个答案:

答案 0 :(得分:4)

1。关于引用分配给变量的值

一个非常常见的错误是使用:

set variable="value with spaces"

这会将"value with spaces"和其他所有内容分配到行尾,就像尾随空格一样variable

第一个双引号的正确定位是:

set "variable=value with spaces"

这将value with spacesvariable分配给此行上的尾随空格或标签。

有关详细信息,请参阅我在Why is no string output with 'echo %var%' after using 'set var = text' on command line?

上的回答

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。 GUI和控制台窗口中的代码页

在德国,GUI上用于非Unicode字符串的代码页为Windows-1252

但默认情况下,在控制台窗口中OEM code page 850在德国使用。

在比较两个表时可以看出德国元音变音在这两个代码页中具有不同的字节值,这解释了你所看到的内容。

默认情况下在控制台窗口中使用的代码页可以通过打开命令提示符窗口看到,并在那里运行命令 chcp ,不带任何参数或命令模式,不带任何参数。在这两种情况下,使用的代码页都在控制台窗口中输出。

命令 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文件现在由命令行解释器直接解析,用于,而不是使用 findstr

在命令提示符窗口for /?中运行以获取有关此命令的帮助。

当使用 for 和参数/F时,默认情况下会直接解析双引号中的字符串。但是对于此任务,必须解析具有双引号指定的完整路径的文件。因此,usebackq用于在字符串解析时更改 for 行为,以获取文件名,其中双引号中的路径被解释为要解析的文件的名称。

接下来,这个批处理文件只对以下行感兴趣:

URL=https://stackoverflow.com/

因此delims==用于将每一行拆分为字符串,并使用等号作为分隔符。

通缉是留给第一个等号的字符串,第一个等号的所有权利当然也可以包含1个或多个等号。我们使用tokens=1*得到了完全分裂的行为。留给第一个等号的字符串是令牌1,它被分配给循环变量a,而第一个等号后面的所有其他东西都是令牌2,它被分配给循环变量b

对字符串左侧与字符串URL的等号进行不区分大小写的比较,检查是否在文件中找到了感兴趣的行。在这种情况下,作为URL字符串的标记2被分配给环境变量URL,并且通过跳转到标签退出循环,因为不需要进一步解析文件的剩余行。

如果 for 循环正常结束,* .url文件中的任何行都不会以URL=开头。然后,在使用goto :EOF退出批处理文件之前,结果是一条适当的信息消息(EOF - 文件结束 - 现在因为预定义标签而一直存在)。

否则,在退出此演示批处理文件之前输出找到的URL。

在命令提示符窗口中使用

调用此批处理文件
D:\4all\reisen\istanbul\verkehr\fähren\Bosp_eminönü_2h_14h30_12tl_SehirHatlari.url

或从Windows资源管理器中使用德语变音符号打开文件并解析它没有问题。

Questioner问道:

是否可以根据窗体是否调用.bat或.exe来传递参数?

对于文件和目录名称,这是真的。

文件关联中的

"%1"是参数的占位符,通常是文件或目录的名称。

Windows现在有3种可能将目录或文件名传递给应用程序:

  1. 对于路径和文件名本身中的所有目录,使用8.3 format的简短格式。 8.3表示目录/文件名最多只能包含8个字符,文件扩展名最多只能包含3个字符,且字符集非常有限。如果要启动的应用程序(.com或.exe)是根据要启动的应用程序的标头的16位应用程序,则Windows使用此格式。

  2. 仅使用ANSI字符的长格式,即每个字符1个字节,末尾为空字节作为终止。如果应用程序是32位或64位应用程序(根据标头而不支持Unicode),则Windows将使用此格式。对于非Unicode感知应用程序,字符串中带有Unicode字符的目录和文件名将转换为system locale代码页。用户可以在Windows 区域和语言设置中设置非Unicode感知应用程序的系统区域设置。

  3. 使用Unicode字符的长格式,即如果要启动的应用程序根据其标题识别Unicode,则每个字符使用2个字节。

  4. ANSI字符串在Windows的C / C ++编码应用程序中使用 char 类型的数组,而类型 wchar_t 的数组用于Unicode字符串。可以找到适用于Windows的C / C ++程序员的详细信息

    如果Windows应该以长格式传递文件或目录名,并且永远不会以短格式传递给"%L",则可以使用

    "%1"代替HKEY_CLASSES_ROOT进行文件关联。一个应用程序。如果应用程序是一个混合体,例如使用DJGPP编译的C / C ++控制台应用程序,这是一个16位应用程序,但由于特殊的启动代码支持长ANSI编码的文件名,有时需要这样做。

    但回到这个问题:是的,当然,Windows会根据可执行文件的标题将文件和目录名称不同地传递给批处理文件或可执行文件,即它是哪种应用程序以及它支持哪种类型的字符串。

    看起来使用的bat to exe转换器创建了一个支持Unicode的64位控制台应用程序。因此,此应用程序必须使用用户帐户的系统区域设置将Unicode字符串转换为ANSI字符串,以便传递文件和目录名称以及最终运行嵌入式批处理文件的命令的其他参数。看起来这个转换器使这个Unicode到ANSI转换任务或创建命令行来运行批处理文件不是100%正确。