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

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

??匹配的数量是 1 和 2
  1. dir /b /a-d *_??.pdf
复制代码
powershell 中 ?? 匹配数量是 2
  1. Get-ChildItem *_??.txt
复制代码
为什么 cmd 中是这样?

回复 17# hnfeng


    是我表达有误,而且有些武断,并没有做测试就想当然啦。
    当时想的是windows不能创建没有文件名,只有后缀的文件,所以自动把 .bin 这样的情况给略过了。
    本意就是想说两种写法结果会不一样。

    不过你的说法也有问题哦, zzzz.bin 是不会被匹配的,因为字母范围只到 f。

TOP

回复 28# WHY

记得有一个方法,用 set/a 计算字符串,把字符串 替换成 -1-1-1.... 这样的,效率高些

TOP

回复 28# WHY


    赞一个,很棒的技巧

TOP

基于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没有字符串长度计算的内部或外部命令,我认为即便是高效的二分法也不会比字符偏移法来的方便、直接。

TOP

本帖最后由 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
复制代码

TOP

本帖最后由 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
复制代码

TOP

经研究试验,发现 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
复制代码

TOP

回复 14# hnfeng
唯一区别后者可以匹配到文件“.bin”(即文件名为空的bin文件),其它都一样。

TOP

多谢楼上各位,学习了学习了

TOP

本帖最后由 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

评分人数

TOP

通过 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

评分人数

    • 77七: 感谢分享技术 + 1

TOP

回复 19# WHY


   谢谢大佬指点!findstr 正则不支持指定重复次数,太遗憾了..
bat小白,请多指教!谢谢!

TOP

本帖最后由 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

评分人数

    • 77七: 感谢分享技术 + 1

TOP

回复 6# Batcher


    以cmd的这边来看,cmd的规则才是正经的,其他的都是不正经的

TOP

返回列表