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

[其他] 讨论:用dir/b在for /f...()中获取非当前目录中的文件属性值如%%~tF,%%~zF的问题

[复制链接]
发表于 2025-8-13 13:27:53 | 显示全部楼层 |阅读模式
本帖最后由 aloha20200628 于 2025-8-14 12:52 编辑


偶然发现以下代码竟然获取 %%~tF, %%~zF 失效?其失效条件》似乎是当变量 %f% 指向一个 '非当前目录' 时怪相即现(已在 win8.1, win10 验证)...

获取 %%~tF, %%~zF 无效的示例一》匹配一组真实存在的文件

  1. @echo off &set "f=d:\temp\*.txt"
  2. for /f "delims=" %%F in ('dir /b "%f%" ') do echo.%%~fF / %%~tF / %%~tF /
  3. pause&exit/b
复制代码
获取 %%~tF, %%~zF 无效的示例二》锚定一个真实存在的文件

  1. @echo off &set "f=d:\temp\abc.txt"
  2. for /f "delims=" %%F in ('dir /b "%f%" ') do echo.%%~fF / %%~tF / %%~tF /
  3. pause&exit/b
复制代码
如果以上代码中的 dir /b 改为 dir /b/s 则获取生效(但会改变文件匹配范围);或者改为以下代码亦可获取生效

有效获取 %%~tF, %%~zF 的示例代码

  1. @echo off &set "f1=d:\temp\*.txt" &set "f2=d:\temp\abc.txt"
  2. for %%F in ("%f1%") do echo.%%~fF / %%~tF / %%~tF /
  3. for %%F in ("%f2%") do echo.%%~fF / %%~tF / %%~tF /
  4. pause&exit/b
复制代码
发表于 2025-8-13 15:06:48 | 显示全部楼层
就像在国内问首都面积多大?得到的是北京的面积;但是在美国问,就需要 加上地址,中国首都面积多大?才能知道北京的面积,否则得到的是华盛顿的面积,当然这是美国有首都的前提下,如果没有首都,就不知道结果了。
发表于 2025-8-13 18:38:47 | 显示全部楼层
%%~tF, %%~zF是拓展for中的自变量F ,不是for中的set
dir /b的结果只有文件的名字 ,拓展时根本就不知道是哪里的文件名字 ,因为不知道 ,所以只能使用当前路径了 ,因此%~dpF之类的也不准确

评分

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

查看全部评分

 楼主| 发表于 2025-8-13 18:49:10 | 显示全部楼层
本帖最后由 aloha20200628 于 2025-8-13 19:00 编辑


问题的缘起是针对一组或一个真实存在的文件,例如一楼代码1-2段中的 %%~fF 均可获得全路径真实值,而获取其 %%~tF, %%~zF 却是空值?但若只要追加 dir /b/s 则即可有效获取 %%~tF, %%~zF 的真实值了  ...
发表于 2025-8-13 21:10:19 | 显示全部楼层
假如需要复制d:\test\1.txt ,在d:\test\路径下,执行命令 copy 1.txt f:\test\1.txt ,没写1.txt的路径,默认工作路径为1.txt 的路径。
假如需要获取d:\test\1.txt 的大小,在d:\test\路径下,执行命令,for /f "delims=" %%i in ("1.txt") do echo %%~zi 没写路径,默认工作路径为1.txt 的路径。

假如需要获取f:\test\1.txt 的大小,我们仍在 d:\test\路径下执行:
for /f "delims=" %%i in ('dir /b "f:\test\1.txt"') do echo %%~zi
这条命令是由两条命令组合而成,dir 和 for /f
分解一下, 第一条 dir命令 的结果是1.txt,将结果直接写入第二条命令,得到
for /f "delims=" %%i in ("1.txt") do echo %%~zi
此时我们发现,这条命令有点眼熟,没错,就是我们第二个假如中的命令,工作路径也一模一样,没写路径,默认工作路径为 1.txt的路径。


而如果把第3个假如中的dir加上 /s ,dir的结果可能是 f:\test\1.txt 和 f:\test\a\1.txt,范围改变了,结果也加上了路径,再次分解
for /f "delims=" %%i in ("f:\test\1.txt") do echo %%~zi
for /f "delims=" %%i in ("f:\test\a\1.txt") do echo %%~zi

评分

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

查看全部评分

 楼主| 发表于 2025-8-14 00:07:56 | 显示全部楼层
本帖最后由 aloha20200628 于 2025-8-14 11:07 编辑


   又扎到中外老帖中练了一把作业。
   回到 dir /b 原形,就是该选项只返回没有全路径的 '路径名和文件名' (除隐含全路径 %%~fF 数据外不再存取其他属性数据如 %%~tF,%%~zF 等)
   假设 c:\tmp\abc.txt 位于当前目录,d:\tmp\xyz.txt 位于非当前目录,可见有如下返回值
        dir /b abc.txt 》abc.txt
        dir /b c:\tmp\abc.txt 》abc.txt
        dir /b d:\tmp\xyz.txt 》xyz.txt
   但由于系统会 '实时' 存取当前目录的各种有关数据,而对那些 '海量的非当前目录' 则不会
   因此  for /f %%F in ('dir /b abc.txt') do echo.%%~zF,%%~tF  便可获取真实返回值
   而  for /f %%F in ('dir /b d:\tmp\xyz.txt') do echo.%%~zF,%%~tF  只是获取空值
   如果加持了 dir /b/s 选项,即如 for /f %%F in ('dir /b/s d:\tmp\xyz.txt') do echo.%%~zF,%%~tF 则亦可获取真实返回值,推测这是因为 /s 让 dir 寻址每一个子目录时将其当成了当前目录...
   谢谢 77七,Five66 参与讨论
发表于 2025-8-14 19:03:00 | 显示全部楼层
回复 4# aloha20200628


    额 ,%%~fF 均可获得全路径真实值中的真实指啥??
%%~fF确实能获得全路径 ,但是那不是fake值??
发表于 2025-8-14 19:08:58 | 显示全部楼层
%%~fF得到的也不会是真实值。
之前似乎讨论过变量增强扩展的问题http://www.bathome.net/redirect.php?goto=findpost&pid=288893&ptid=70853
只要用了变量增强扩展,就会用GetFullPathName获取全路径,然后再基于此进行切分或其他处理。
问题出在GetFullPathName函数上,如果你只是set一个文件名,那么GetFullPathName获取全路径的方法就是将当前目录与指定的文件名(不管这个文件是否真实存在)进行拼接。
https://learn.microsoft.com/zh-cn/windows/win32/api/fileapi/nf-fileapi-getfullpathnamew
 楼主| 发表于 2025-8-14 19:51:29 | 显示全部楼层
回复 8# buyiyang
回复 7# Five66

是的,6楼以前一直还在疑问中...
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-3-17 12:43 , Processed in 0.019132 second(s), 9 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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