标题: [文件操作] 批处理命令dir 中 ? 的匹配问题 [打印本页]
作者: newswan 时间: 2024-2-1 12:33 标题: 批处理命令dir 中 ? 的匹配问题
??匹配的数量是 1 和 2复制代码
powershell 中 ?? 匹配数量是 2复制代码
为什么 cmd 中是这样?
作者: Five66 时间: 2024-2-1 19:21
额,powershell中的问号(?)匹配一个字符,大概是powershell自己的规则
如果想要像cmd那样,试试用-Filter选项
Get-ChildItem -Filter *_??.txt
作者: 77七 时间: 2024-2-2 00:23
?匹配0个、1个,??匹配0个、1个、2个
作者: hnfeng 时间: 2024-2-2 10:50
本帖最后由 hnfeng 于 2024-2-2 11:03 编辑
那么,在cmd中,如何仅匹配:
0fca724925a0312d9261912bfe810eaa.bin
0fcbc1c2d20b8724f538718827a97d85.bin
0fe920300e68d25db45c915c0c755d73.bin
0ff4803731ace688f5ec1333ff40d569.bin
(32个 由0-9和a-f组成的字符串).bin
又不会误伤 正常的少于32个字符的普通 .bin 文件?
作者: qixiaobin0715 时间: 2024-2-2 11:03
回复 3# 77七
cmd还是有点奇葩,dir时,如果问号在前面看看会发生什么。
比如有这样一些文件:
abc123.txt
bc123.txt
c123.txt
123.txt
分别执行dir命令:
dir /b /a-d ???123.txt
dir /b /a-d ??123.txt
dir /b /a-d ?123.txt
结果是什么?
作者: Batcher 时间: 2024-2-2 11:29
回复 2# Five66
恰恰相反,正经的通配符:
? 匹配1个字符
* 匹配0个或1个或任意多个字符
反而是CMD自己的规则不符大多数软件和人的共识
作者: 77七 时间: 2024-2-2 13:47
本帖最后由 77七 于 2024-2-2 13:49 编辑
回复 5# qixiaobin0715
谢谢大佬指点!
经过测试发现,当一个?或者连续多个?出现在开头,且点号之前不全是?(出现其它字符),其它字符之前的?只匹配1个,其它字符之后的?匹配0个,1个。
如
- @echo off
- >123.txt cd.
- dir /b /a-d ????.txt
- echo=
- dir /b /a-d ??3.txt
- echo=
- dir /b /a-d ??3?.txt
- pause
复制代码
三个dir 命令全部匹配成功
另外发现问号"?"对点号 "."匹配失败
- @echo off
- >12.3.txt cd.
- dir /b /a-d ???3.txt
- echo=
- dir /b /a-d ??.3.txt
- pause
复制代码
作者: 77七 时间: 2024-2-2 13:52
回复 4# hnfeng
发现32个[0-9a-z]提示过长,所以用了两个findstr匹配
- dir /b /a-d |findstr /rixc:"................................\.bin" |findstr /rixc:"[0-9a-z][0-9a-z]*\.bin"
复制代码
作者: hnfeng 时间: 2024-2-2 16:37
回复 8# 77七
不知道为什么,不成功。- C:\temp\2.8Bin>dir /s /b /a-d
- C:\temp\2.8Bin\ShaderCache\0\00a356bb4dcffadfbecc027ff2f0f3f5.bin
- C:\temp\2.8Bin\ShaderCache\0\00abace58a961221e6c54cc17e90d1c3.bin
- C:\temp\2.8Bin\ShaderCache\0\00afde0f28ad42f7e08ce48672c2d6a8.bin
- C:\temp\2.8Bin\ShaderCache\a\a00e46701b2ebba310eb944fb78268a2.bin
- C:\temp\2.8Bin\ShaderCache\a\a0a2d4feb4186b3994675cb5cb6105c6.bin
- C:\temp\2.8Bin\ShaderCache\a\a0a67596c850febb29bde5f1c15e1839.bin
- C:\temp\2.8Bin\test\acddffdg hgfjhjjkjkj.bin
- C:\temp\2.8Bin\test\dfdgfdg hjhjkjk.bin
- C:\temp\2.8Bin\test\ffffffffff abcd.bin
-
- C:\temp\2.8Bin>dir /s /b /a-d |findstr /rixc:"................................\.bin" |findstr /rixc:"[0-9a-z][0-9a-z]*\.bin"
-
- C:\temp\2.8Bin>dir /s /b /a-d |findstr /rixc:"................................\.bin"
-
- C:\temp\2.8Bin>dir /s /b /a-d |findstr /rixc:"[0-9a-f][0-9a-f]*\.bin"
-
- C:\temp\2.8Bin>dir /s /b /a-d |findstr /rixc:"[0-9a-f]*\.bin"
-
- C:\temp\2.8Bin>dir /s /b /a-d |findstr /rixc:"[0-9a-f]*"
-
- C:\temp\2.8Bin>dir /s /b /a-d |findstr /rixc:"f.*"
-
- C:\temp\2.8Bin>dir /s /b /a-d |findstr /rixc:".*\.bin"
- C:\temp\2.8Bin\ShaderCache\0\00a356bb4dcffadfbecc027ff2f0f3f5.bin
- C:\temp\2.8Bin\ShaderCache\0\00abace58a961221e6c54cc17e90d1c3.bin
- C:\temp\2.8Bin\ShaderCache\0\00afde0f28ad42f7e08ce48672c2d6a8.bin
- C:\temp\2.8Bin\ShaderCache\a\a00e46701b2ebba310eb944fb78268a2.bin
- C:\temp\2.8Bin\ShaderCache\a\a0a2d4feb4186b3994675cb5cb6105c6.bin
- C:\temp\2.8Bin\ShaderCache\a\a0a67596c850febb29bde5f1c15e1839.bin
- C:\temp\2.8Bin\test\acddffdg hgfjhjjkjkj.bin
- C:\temp\2.8Bin\test\dfdgfdg hjhjkjk.bin
- C:\temp\2.8Bin\test\ffffffffff abcd.bin
-
- C:\temp\2.8Bin>
复制代码
作者: newswan 时间: 2024-2-2 16:56
dos 从开始,就有缺陷。
首先,抄 unix 的路径分隔符就行,非要反过来。
第二,换行符
第三,获取命令返回值
有谁比较了解这些历史,为什么 dos 不能按照 unix 的习惯。
作者: _avatar_ 时间: 2024-2-2 17:20
回复 6# Batcher
正则中的 ? 不是匹配 0 个或 1个吗?
作者: Batcher 时间: 2024-2-2 17:23
回复 11# _avatar_
6楼说的是通配符,不是正则表达式。二者的区别你可以搜索一下。
作者: Batcher 时间: 2024-2-2 17:32
回复 9# hnfeng
你加了 /s 之后文件名前面增加了路径名,但是你的 findstr 命令使用了 /x 精确匹配,所以出错。改成这样试试:- dir /s /b /a-d |findstr /r /i /c:"\\................................\.bin" | findstr /e /r /i /c:"\\[0-9a-f][0-9a-f]*\.bin"
复制代码
作者: hnfeng 时间: 2024-2-2 18:59
回复 13# Batcher
谢谢,可以了
我原以为只要含有引号内所定义的字符就算匹配成功
另外,请教 "\\[0-9a-f][0-9a-f]*\.bin" 是不是与 "\\[0-9a-f]*\.bin" 相同效果?
作者: _avatar_ 时间: 2024-2-2 21:10
回复 12# Batcher
是我理解有误,我一直以为cmd中的通配符跟 正则中的量词是一样的。
作者: _avatar_ 时间: 2024-2-2 21:18
回复 Batcher
请教 "\\[0-9a-f][0-9a-f]*\.bin" 是不是与 "\\[0-9a-f]*\.bin" 相同效果?
hnfeng 发表于 2024-2-2 18:59
并不相同哦,前一个 [0-9a-f] 是一定会有一个字符需要匹配,后面的 [0-9a-f]* 是匹配0个或多个。
也就是说 "\\[0-9a-f][0-9a-f]*\.bin" 可以匹配到一个字符的结果,也可以匹配到两个字符的结果,比如 d.bin 、 3.bin 、 af.bin 、 0c.bin ,但 "\\[0-9a-f]*\.bin" 就只能匹配一个字符的结果,比如 d.bin 、 3.bin
作者: hnfeng 时间: 2024-2-2 21:38
本帖最后由 hnfeng 于 2024-2-2 21:41 编辑
回复 16# _avatar_
我怎么感觉是这样的:
[0-9a-f][0-9a-f]* 是 一个 [0-9a-f] 再跟0个或多个 [0-9a-f],结果可能是 a.bin, ab.bin,abcdef12345.bin, abcdef12_345.bin .....
[0-9a-f]* 是 0个或多个 [0-9a-f],可以不含 [0-9a-f],结果可能是 上面那些,也可能是 zzzz.bin ...
作者: Five66 时间: 2024-2-2 22:11
回复 6# Batcher
以cmd的这边来看,cmd的规则才是正经的,其他的都是不正经的
作者: WHY 时间: 2024-2-3 23:08
本帖最后由 WHY 于 2024-2-4 11:24 编辑
回复 8# 77七
可以先用 findstr 确定全部由[a-f0-9]组成,再用字符偏移定位其长度,这样用1个findstr即可。
findstr 正则不支持表示范围的量词,只能选择折中方案。
举例:- @echo off
- setlocal enabledelayedexpansion
- for /f "delims=" %%i in ('dir /b /a-d *.bin ^| findstr /i "^[0-9a-f][0-9a-f]*\.bin$"') do (
- set "name=%%~ni"
- if "!name:~32!" == "" (
- if "!name:~31!" NEQ "" echo;%%i
- )
- )
- pause
复制代码
作者: 77七 时间: 2024-2-4 11:38
回复 19# WHY
谢谢大佬指点!findstr 正则不支持指定重复次数,太遗憾了..
作者: WHY 时间: 2024-2-4 11:38
通过 findstr 管道套管道,能够解决4楼提出的具体问题,但并不通用,源于 findstr 不支持{m,n}这种表示范围的量词。
比如条件变一下:查找大于等于16个字符,小于等于32个字符,全部由[a-f0-9]组成的 .bin 文件。
这个时候如果仅仅用 findstr 来解,即使真能够实现,相信也是异常麻烦。
可以采用这种办法:- @echo off
- setlocal enabledelayedexpansion
- for /f "delims=" %%i in ('dir /b /a-d *.bin ^| findstr /i "^[0-9a-f][0-9a-f]*\.bin$"') do (
- set "name=%%~ni"
- if "!name:~32!" == "" (
- if "!name:~15!" NEQ "" echo;%%i
- )
- )
- pause
复制代码
作者: qixiaobin0715 时间: 2024-2-4 16:23
本帖最后由 qixiaobin0715 于 2024-2-5 09:21 编辑
使用findstr筛选确实麻烦:- @echo off
- setlocal enabledelayedexpansion
- for /l %%i in (1,1,32) do (
- set n1=!n1!.
- if %%i equ 16 set n2=!n1!
- )
- dir /b /a-d *.bin|findstr /i "^[0-9a-f][0-9a-f]*\.bin$"|findstr /v !n1!.\.bin|findstr !n2!\.bin
- pause
复制代码
作者: hnfeng 时间: 2024-2-5 08:35
多谢楼上各位,学习了学习了
作者: qixiaobin0715 时间: 2024-2-5 09:27
回复 14# hnfeng
唯一区别后者可以匹配到文件“.bin”(即文件名为空的bin文件),其它都一样。
作者: hnfeng 时间: 2024-2-5 10:12
经研究试验,发现 19楼的方法完美。
另外,我原以为 findstr /eric:"\\................................\.bin" 会列出文件名是 32位及不足32位的.bin文件(32个".", 1个"."代表任意一个字符), 今天意外发现 ,并不是全部不足32位文件名的文件都能列出来。
我产生了用1-50个1、1-50个a、a开头后面跟1-50个1的bin文件,结果发现,只有文件名位数是 15位,20位,27位,32位的文件才能被列出来,不知原因,高手们给解释一下?
下面是试验的命令:- for /f "delims=" %i in ('dir /b /s /a-d *.bin ^| findstr /eric:"\\................................\.bin"') do @echo %i
复制代码
作者: qixiaobin0715 时间: 2024-2-5 10:25
本帖最后由 qixiaobin0715 于 2024-2-5 10:37 编辑
回复 25# hnfeng
代码中一系列的 . 在findstr中可以代表任意字符,包括路径中的 \ 。想一想就应当能够明白其中的问题了。
在你实验命令的路径中,下面命令应当能匹配15个字符的文件名(我是把连续的 . 中倒数第16个 . 替换成 \\ 而已):- for /f "delims=" %i in ('dir /b /s /a-d *.bin ^| findstr /eric:"\\................\\...............\.bin"') do @echo %i
复制代码
作者: qixiaobin0715 时间: 2024-2-6 10:09
本帖最后由 qixiaobin0715 于 2024-2-6 14:40 编辑
用dir+findstr命令筛选文件名时最好不要带上路径字符,有时会带来不必要的麻烦,还是一步步的来比较简单明了,虽然代码行数会增加,但效率上不见得低多少:- @echo off
- for /f "delims=" %%i in ('dir /s /b /ad') do (
- if exist "%%i\*.bin" (
- pushd "%%i"
- for /f "delims=" %%j in ('dir /b /a-d^|findstr "................................\.bin"') do echo,%%~fj
- popd
- )
- )
- pause
复制代码
作者: WHY 时间: 2024-2-7 00:01
基于21楼的补充
1.查找大于等于32个字符、全部由[0-9a-f]组成、包括子目录里面的 .bin 文件:- @echo off
- setlocal enabledelayedexpansion
- for /f "delims=" %%i in ('dir /b /a-d /s *.bin ^| findstr /i "\\[0-9a-f][0-9a-f]*\.bin$"') do (
- set "name=%%~ni"
- if "!name:~31!" NEQ "" echo;%%i
- )
- pause
复制代码
2.查找小于等于32个字符、全部由[0-9a-f]组成、包括子目录里面的 .bin 文件:- @echo off
- setlocal enabledelayedexpansion
- for /f "delims=" %%i in ('dir /b /a-d /s *.bin ^| findstr /i "\\[0-9a-f][0-9a-f]*\.bin$"') do (
- set "name=%%~ni"
- if "!name:~32!" == "" echo;%%i
- )
- pause
复制代码
题外话:
网上看到过很多判断文件名长度的提问与回答,其中bat的回答基本上都是先计算字符串长度,再与给定数值进行比较。
其实没有必要,判断字符串长度与计算字符串长度不是一码事。
判断是事先给你一个已知数值,而计算肯定不会给你数值的。这是其一;
其二,CMD没有字符串长度计算的内部或外部命令,我认为即便是高效的二分法也不会比字符偏移法来的方便、直接。
作者: hnfeng 时间: 2024-2-7 14:26
回复 28# WHY
赞一个,很棒的技巧
作者: newswan 时间: 2024-2-7 14:28
回复 28# WHY
记得有一个方法,用 set/a 计算字符串,把字符串 替换成 -1-1-1.... 这样的,效率高些
作者: _avatar_ 时间: 2024-2-12 13:20
回复 17# hnfeng
是我表达有误,而且有些武断,并没有做测试就想当然啦。
当时想的是windows不能创建没有文件名,只有后缀的文件,所以自动把 .bin 这样的情况给略过了。
本意就是想说两种写法结果会不一样。
不过你的说法也有问题哦, zzzz.bin 是不会被匹配的,因为字母范围只到 f。
欢迎光临 批处理之家 (http://www.bathome.net/) |
Powered by Discuz! 7.2 |