批处理搜索提取二进制文件小记
最近完成了一个批处理,功能是打开快捷方式(*.lnk)指向的文件所在的目录。其中使用到一些有意思的小技巧,这篇短文记录下一步步实现这个功能的过程,和大家一起分享一下。
我们首先要做的是先分析一下快捷方式的内容,为记事本创建两个快捷方式作为例子。第一个 notepad.lnk ,目标处填入 c:\WINDOWS\system32\notepad.exe ;第二个 notepad2.lnk ,目标处填入 %windir%\system32\notepad.exe 。我们知道快捷方式是以二进制文件的形式存在的,用任意一款十六进制编辑软件打开 notepad.lnk 与 notepad2.lnk 观察一下。提示一下部分编辑软件会打开指向的文件而不是快捷方式,但一般都有设置选项可以更改,具体软件的使用情况不做过多的说明。打开后会发现无论哪种方式建立的快捷方式都会找到一串字符 C:\WINDOWS\system32\notepad.exe ,现在要做的就是把这串字符提取出来。想想我们可以用到的命令好像只有 find 和 findstr 两个,两个命令都能够进行二进制文件的搜索,他们各有优缺点,find 会将搜到的二进制信息分行显示,findstr 会原样显示二进制信息,后者的强项是支持简单的正则表达式。我们利用两个命令的组合将所要的信息提取出来。
我们先看一下合法的文件与文件夹的全路径都会有哪些组合:
c:\
c:\windows
c:\windows\
c:\windows\explorer.exe
D:\TeSt\.\
D:\TeSt\test1\test2
D:\TeSt\tEsT.txt.lnk
D:\TeSt\tEsT (2).txt.lnk
D:\TeSt\tEsT (3).txt.lnk 不存在
还有其他类似的组合,等等,哪怕最后一个看起来有些怪异仍是可能存在的。用 PERL 样式的正则表达式多行模式下可能需要这样描述“^(:\\)(.+?\\)*.*$”,但这个表达式不够严格,更好一点的应该这样写“^(:\\)((+\\)*)()*$”,如果不幸在一行上的话可能需要这样匹配“(:\\)(((?!:))*)”。我们在这里只是讨论一下完整路径名形式的特征,不多谈 PERL 正则表达式。回到我们的问题上来,不管那样的组合都会出现 “盘符:\” 这样字符组合,据此可以提取出我们想要的字串。先用 find 过滤一下,find ":" *.lnk ,观察一下结果会发现我们想要的字串在一行上,再用 findstr 二次过滤一下就 OK 了,find ":" *.lnk |findstr /r "^:" ,findstr 的 /r 参数表明搜索的字符串为一般表达式,“^”匹配行的开始,“”字符集表示匹配大小写的字母。重点谈一下 findstr 查找 “\” 字符,在其他的正则表达式中一般在字符前添加 “\”会脱掉元字符的特殊性,简单说就是两个 “\\” 表示一个 “\” 。而在 findstr 却要用四个代替一个,比如查找字符“D:\”需要这样来写 findstr "D:\\\\" ,如果查找多个连续的“\” 如:“D:\\\” 会把人搞晕的,另一个方法是利用字符集两个成表示一个,这个例子可以这样来写,findstr /r "D:" 。继续回到我们的问题,勤于思考的朋友会问,如果某快捷方式的路径为 “盘符:” 我们的查找会不会失败,这种情况是不会出现的,不信可建立一个快捷方式,目标位置填入 “C:” 会发现 widows 自动在后面添加上一个 “\”。
事实上还有一个命令会格式化二进制文件输出,就是 more ,如命令:more /s notepad.lnk |findstr /r "^:" ,会输出同样的效果,但是 more 非交互方式下不能应用于多文件,如命令:more /s *.lnk |findstr /r "^:" ,会一直等待用户的按键。非用 more 的不可情况是 find 无法完成第一遍过滤,比如搜索的是一个表达式没有简单的固定特征字符的情况。
最后给出我们的成果。可以放到 sendto 文件夹下,或命令行调用。
后记:我一直希望有更多的人了解批处理并对此感兴趣,尝试性的写一些小短文,发觉并不顺手,可能有些批处理知识的朋友看的会更累。效仿了一下 3742668 兄爱用的 mode 命令,让批处理错误提示更有趣了。
如果希望在快捷方式上直接右键打开目录的话,可以参考下面的注册表项修改一下。
最近完成了一个批处理,功能是打开快捷方式(*.lnk)指向的文件所在的目录。其中使用到一些有意思的小技巧,这篇短文记录下一步步实现这个功能的过程,和大家一起分享一下。
我们首先要做的是先分析一下快捷方式的内容,为记事本创建两个快捷方式作为例子。第一个 notepad.lnk ,目标处填入 c:\WINDOWS\system32\notepad.exe ;第二个 notepad2.lnk ,目标处填入 %windir%\system32\notepad.exe 。我们知道快捷方式是以二进制文件的形式存在的,用任意一款十六进制编辑软件打开 notepad.lnk 与 notepad2.lnk 观察一下。提示一下部分编辑软件会打开指向的文件而不是快捷方式,但一般都有设置选项可以更改,具体软件的使用情况不做过多的说明。打开后会发现无论哪种方式建立的快捷方式都会找到一串字符 C:\WINDOWS\system32\notepad.exe ,现在要做的就是把这串字符提取出来。想想我们可以用到的命令好像只有 find 和 findstr 两个,两个命令都能够进行二进制文件的搜索,他们各有优缺点,find 会将搜到的二进制信息分行显示,findstr 会原样显示二进制信息,后者的强项是支持简单的正则表达式。我们利用两个命令的组合将所要的信息提取出来。
我们先看一下合法的文件与文件夹的全路径都会有哪些组合:
c:\
c:\windows
c:\windows\
c:\windows\explorer.exe
D:\TeSt\.\
D:\TeSt\test1\test2
D:\TeSt\tEsT.txt.lnk
D:\TeSt\tEsT (2).txt.lnk
D:\TeSt\tEsT (3).txt.lnk 不存在
还有其他类似的组合,等等,哪怕最后一个看起来有些怪异仍是可能存在的。用 PERL 样式的正则表达式多行模式下可能需要这样描述“^(:\\)(.+?\\)*.*$”,但这个表达式不够严格,更好一点的应该这样写“^(:\\)((+\\)*)()*$”,如果不幸在一行上的话可能需要这样匹配“(:\\)(((?!:))*)”。我们在这里只是讨论一下完整路径名形式的特征,不多谈 PERL 正则表达式。回到我们的问题上来,不管那样的组合都会出现 “盘符:\” 这样字符组合,据此可以提取出我们想要的字串。先用 find 过滤一下,find ":" *.lnk ,观察一下结果会发现我们想要的字串在一行上,再用 findstr 二次过滤一下就 OK 了,find ":" *.lnk |findstr /r "^:" ,findstr 的 /r 参数表明搜索的字符串为一般表达式,“^”匹配行的开始,“”字符集表示匹配大小写的字母。重点谈一下 findstr 查找 “\” 字符,在其他的正则表达式中一般在字符前添加 “\”会脱掉元字符的特殊性,简单说就是两个 “\\” 表示一个 “\” 。而在 findstr 却要用四个代替一个,比如查找字符“D:\”需要这样来写 findstr "D:\\\\" ,如果查找多个连续的“\” 如:“D:\\\” 会把人搞晕的,另一个方法是利用字符集两个成表示一个,这个例子可以这样来写,findstr /r "D:" 。继续回到我们的问题,勤于思考的朋友会问,如果某快捷方式的路径为 “盘符:” 我们的查找会不会失败,这种情况是不会出现的,不信可建立一个快捷方式,目标位置填入 “C:” 会发现 widows 自动在后面添加上一个 “\”。
事实上还有一个命令会格式化二进制文件输出,就是 more ,如命令:more /s notepad.lnk |findstr /r "^:" ,会输出同样的效果,但是 more 非交互方式下不能应用于多文件,如命令:more /s *.lnk |findstr /r "^:" ,会一直等待用户的按键。非用 more 的不可情况是 find 无法完成第一遍过滤,比如搜索的是一个表达式没有简单的固定特征字符的情况。
最后给出我们的成果。可以放到 sendto 文件夹下,或命令行调用。
无奈何发表于 2006-10-25 17:57
- @echo off
- if "%~1" == "" goto :EOF
- ::检查扩展名是否是快捷方式文件
- if /i "%~x1" NEQ ".lnk" goto error
- for /f "delims=" %%i in ('find ":" "%~1" ^|findstr /r "^:"') do (
- start %%~dpi
- )
- goto :EOF
- :error
- ::抛出错误提示窗口
- start cmd /c "title 提示!&mode con cols=30 lines=5 &for /l %%i in (5,-1,1) do cls &echo. 所选文件不是快捷方式!( %%i )&ping/n 2 127.1>nul"
后记:我一直希望有更多的人了解批处理并对此感兴趣,尝试性的写一些小短文,发觉并不顺手,可能有些批处理知识的朋友看的会更累。效仿了一下 3742668 兄爱用的 mode 命令,让批处理错误提示更有趣了。
如果希望在快捷方式上直接右键打开目录的话,可以参考下面的注册表项修改一下。
Windows Registry Editor Version 5.00
@="打开指向目录"
@="\"D:\\BAT\\ShortcutOpen.cmd\" \"%1\""
☆开始\运行 (WIN+R)☆
%ComSpec% /cset,=何奈无── 。何奈可无是原,事奈无做人奈无&for,/l,%i,in,(22,-1,0)do,@call,set/p= %,:~%i,1%<nul&ping/n 1 127.1>nul
%ComSpec% /cset,=何奈无── 。何奈可无是原,事奈无做人奈无&for,/l,%i,in,(22,-1,0)do,@call,set/p= %,:~%i,1%<nul&ping/n 1 127.1>nul
