找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
楼主: newswan

[文件操作] 批处理命令dir 中 ? 的匹配问题

[复制链接]
发表于 2024-2-2 21:18:16 | 显示全部楼层
回复  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
发表于 2024-2-2 21:38:33 | 显示全部楼层
本帖最后由 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 ...
发表于 2024-2-2 22:11:24 | 显示全部楼层
回复 6# Batcher


    以cmd的这边来看,cmd的规则才是正经的,其他的都是不正经的
发表于 2024-2-3 23:08:46 | 显示全部楼层
本帖最后由 WHY 于 2024-2-4 11:24 编辑

回复 8# 77七


    可以先用 findstr 确定全部由[a-f0-9]组成,再用字符偏移定位其长度,这样用1个findstr即可。
findstr 正则不支持表示范围的量词,只能选择折中方案。
举例:
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. for /f "delims=" %%i in ('dir /b /a-d *.bin ^| findstr /i "^[0-9a-f][0-9a-f]*\.bin$"') do (
  4.     set "name=%%~ni"
  5.     if "!name:~32!" == "" (
  6.         if "!name:~31!" NEQ "" echo;%%i
  7.     )
  8. )
  9. pause
复制代码

评分

参与人数 1技术 +1 收起 理由
77七 + 1 感谢分享

查看全部评分

发表于 2024-2-4 11:38:05 | 显示全部楼层
回复 19# WHY


   谢谢大佬指点!findstr 正则不支持指定重复次数,太遗憾了..
发表于 2024-2-4 11:38:42 | 显示全部楼层
通过 findstr 管道套管道,能够解决4楼提出的具体问题,但并不通用,源于 findstr 不支持{m,n}这种表示范围的量词。

比如条件变一下:查找大于等于16个字符,小于等于32个字符,全部由[a-f0-9]组成的 .bin 文件。
这个时候如果仅仅用 findstr 来解,即使真能够实现,相信也是异常麻烦。
可以采用这种办法:
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. for /f "delims=" %%i in ('dir /b /a-d *.bin ^| findstr /i "^[0-9a-f][0-9a-f]*\.bin$"') do (
  4.     set "name=%%~ni"
  5.     if "!name:~32!" == "" (
  6.         if "!name:~15!" NEQ "" echo;%%i
  7.     )
  8. )
  9. pause
复制代码

评分

参与人数 1技术 +1 收起 理由
77七 + 1 感谢分享

查看全部评分

发表于 2024-2-4 16:23:59 | 显示全部楼层
本帖最后由 qixiaobin0715 于 2024-2-5 09:21 编辑

使用findstr筛选确实麻烦:
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. for /l %%i in (1,1,32) do (
  4. set n1=!n1!.
  5. if %%i equ 16 set n2=!n1!
  6. )
  7. dir /b /a-d *.bin|findstr /i "^[0-9a-f][0-9a-f]*\.bin$"|findstr /v !n1!.\.bin|findstr !n2!\.bin
  8. pause
复制代码

评分

参与人数 1技术 +1 收起 理由
WHY + 1 +1

查看全部评分

发表于 2024-2-5 08:35:22 | 显示全部楼层
多谢楼上各位,学习了学习了
发表于 2024-2-5 09:27:21 | 显示全部楼层
回复 14# hnfeng
唯一区别后者可以匹配到文件“.bin”(即文件名为空的bin文件),其它都一样。
发表于 2024-2-5 10:12:48 | 显示全部楼层
经研究试验,发现 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位的文件才能被列出来,不知原因,高手们给解释一下?

下面是试验的命令:
  1. for /f "delims=" %i in ('dir /b /s /a-d *.bin ^| findstr /eric:"\\................................\.bin"') do @echo %i
复制代码
发表于 2024-2-5 10:25:49 | 显示全部楼层
本帖最后由 qixiaobin0715 于 2024-2-5 10:37 编辑

回复 25# hnfeng
代码中一系列的 . 在findstr中可以代表任意字符,包括路径中的 \ 。想一想就应当能够明白其中的问题了。
在你实验命令的路径中,下面命令应当能匹配15个字符的文件名(我是把连续的 . 中倒数第16个 . 替换成 \\ 而已):
  1. for /f "delims=" %i in ('dir /b /s /a-d *.bin ^| findstr /eric:"\\................\\...............\.bin"') do @echo %i
复制代码
发表于 2024-2-6 10:09:39 | 显示全部楼层
本帖最后由 qixiaobin0715 于 2024-2-6 14:40 编辑

用dir+findstr命令筛选文件名时最好不要带上路径字符,有时会带来不必要的麻烦,还是一步步的来比较简单明了,虽然代码行数会增加,但效率上不见得低多少:
  1. @echo off
  2. for /f "delims=" %%i in ('dir /s /b /ad') do (
  3.     if exist "%%i\*.bin" (
  4.         pushd "%%i"
  5.         for /f "delims=" %%j in ('dir /b /a-d^|findstr "................................\.bin"') do echo,%%~fj
  6.         popd
  7.     )
  8. )
  9. pause
复制代码
发表于 2024-2-7 00:01:11 | 显示全部楼层
基于21楼的补充
1.查找大于等于32个字符、全部由[0-9a-f]组成、包括子目录里面的 .bin 文件:
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. for /f "delims=" %%i in ('dir /b /a-d /s *.bin ^| findstr /i "\\[0-9a-f][0-9a-f]*\.bin$"') do (
  4.     set "name=%%~ni"
  5.     if "!name:~31!" NEQ "" echo;%%i
  6. )
  7. pause
复制代码
2.查找小于等于32个字符、全部由[0-9a-f]组成、包括子目录里面的 .bin 文件:
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. for /f "delims=" %%i in ('dir /b /a-d /s *.bin ^| findstr /i "\\[0-9a-f][0-9a-f]*\.bin$"') do (
  4.     set "name=%%~ni"
  5.     if "!name:~32!" == "" echo;%%i
  6. )
  7. pause
复制代码
题外话:
网上看到过很多判断文件名长度的提问与回答,其中bat的回答基本上都是先计算字符串长度,再与给定数值进行比较。
其实没有必要,判断字符串长度与计算字符串长度不是一码事。
判断是事先给你一个已知数值,而计算肯定不会给你数值的。这是其一;
其二,CMD没有字符串长度计算的内部或外部命令,我认为即便是高效的二分法也不会比字符偏移法来的方便、直接。
发表于 2024-2-7 14:26:17 | 显示全部楼层
回复 28# WHY


    赞一个,很棒的技巧
 楼主| 发表于 2024-2-7 14:28:08 | 显示全部楼层
回复 28# WHY

记得有一个方法,用 set/a 计算字符串,把字符串 替换成 -1-1-1.... 这样的,效率高些
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-17 19:24 , Processed in 0.069962 second(s), 8 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表