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

[未彻底解决]多个文件拖到cmd窗口后,如何获取每一文件的完整路径

  cmd窗口有一个特点:支持把文件拖曳到cmd窗口中来处理。

  编个十分简单的脚本来演示一下:
  1. @echo off
  2. echo %1
  3. pause
复制代码
  一般的情形是这样的:

  1、当文件的完整路径中带有空格的时候,cmd窗口将自动为文件的完整路径首尾添加一对引号。例如,把 d:\abc xyz 文件夹下的 test.txt 文件拖曳到以上代码所在的脚本文件上之后,将在屏幕上显示: "d:\abc xyz\test.txt"
  2、当文件的完整路径中没有空格的时候,cmd窗口将不会为文件的完整路径添加引号对。例如:把 d:\abcxyz 文件夹下的 test.txt 文件拖曳到以上代码所在的脚本文件上之后,将在屏幕上显示: d:\abcxyz\test.txt。请注意,这个时候,文件路径里没有引号对。

  当然,这只是一般情形。还有一种特殊情形:当文件的完整路径中有&但是不带空格的时候,以上代码将捕获不到正确的路径。比如:把 d:\abcxyz 文件夹下的 test1&test2.txt 文件拖曳到以上代码所在的脚本文件上之后,屏幕上显示的不是 d:\abcxyz\test1&test2.txt,而是显示: d:\abcxyz\test1,也就是说,&后的字符串直接被丢弃掉了。这可能是cmd窗口在捕获or传递参数时的一个bug。

  假设 d:\test 目录下有如下文件,现在把它们同时拖曳到脚本文件上来执行,需要获得每一个文件的完整路径,请问如何编写代码?
  1. abc.txt
  2. abc xyz.txt
  3. abc^xyz.txt
  4. abc&xyz.txt
  5. abc & xyz.txt
  6. (abc)(xyz).txt
  7. (abc) (xyz).txt
  8. (abc)&(xyz).txt
  9. (abc) & (xyz).txt
  10. abc;xyz.txt
  11. abc,xyz.txt
  12. abc=xyz.txt
复制代码
  想到这个问题,是源于这个帖子的讨论: 如何用批处理批量移动文件或文件夹?(http://bbs.bathome.net/thread-7504-1-1.html

  提示:一般情况下,可以用如下代码显示多个文件的完整路径:
  1. @echo off
  2. echo %*
  3. pause
复制代码
=====================================================
qzwqzw 在7楼给出了解释:
用批处理的办法基本无解

这个问题源于Explorer的拖放扩展程序shell32.dll
注册表路径位于HKEY_CLASSES_ROOT\CLSID\{86C86720-42A0-1069-A2E8-08002B30309D}
因为它没有将“&"视为转义符号
所以不会用引号对将其扩起取消转义

所以对于这个问题无非以下几个方案:
1、修改拖放扩展程序shell32.dll,让它可以处理"&"的情况;
2、新建拖放扩展程序,专门处理cmd之类程序的路径过滤;
3、在处理前告知用户使用"&"的情况可能出错,交由用户处理发生的异常;

  既然这样,那么,用批处理来做的话,只好不去兼容带&但不同时带空格的完整路径这一情况了(路径中带有^符号也不行,头疼ing)。演示代码如下:
  1. @echo off
  2. set str=%*
  3. set "str=%str:"=%"
  4. set "str= %str%"
  5. call set "str=%%str: %~d1=" "%~d1%%"
  6. for %%i in ("%str%") do echo %%i
  7. pause
复制代码
尺有所短寸有所长,学好批处理没商量;
考虑问题复杂化,解决问题简洁化。

心在天山,身老沧州。

多数时间是从技巧上寻找突破口,但只要把批处理的

预处理、变量扩展(%time%等)、延迟变量扩展(!time!等)、特殊字符(路径文件名与批处理共享的 ! % & ( ) , ; = ^ 等)

这四个核心概念放到一起,来分析楼主抛出的难题,感觉修改标题为【已解决】的可能性很小!

TOP

此题有解 纯P实现,以%*接收所有参数,然后使用for命令分割处理。

TOP

bat默认把运行参数使用空格符进行分割,即使能够把&进行转义处理,但包含空格的完整路径,将得不到完整的路径。唯一办法:%*接收所有参数,对参数进行文本处理。

TOP

回复 37# cjiabing

上周我遇到类似问题,搞了一星期试了各种方法搞不定
后来换了vbs来处理,处理完再把结果作为参数传递给bat启动,搞定

TOP

回复 36# flaven


    奇怪,我放在桌面上可以执行,放到驱动盘下就出错了!~
    可能路径名含有空格的时候它自动添加双引号,没有空格的时候它没有添加,所以出错了!~

原理是这样的:
1.对于“%*”直接使用    "%*"    (即echo "%*")即可解决问题,但问题是这个结果中的路径都挤到了一行里面,不方面引用。
因此需要考虑第二个问题:拆分路径并去掉双引号。
2.一般情况下,利用dir命令的特点来自动拆分路径和双引号,所以使用  dir /b %*  即可。但现在看来也是存在一定限制。
3.实在不行的情况下,又得回头使用SET替换的方式,或者使用FOR替换的方式,那样会比较麻烦点。
因为文件名含有特殊符号,所以使用双引号,但为了提前单个独立的路径又需要去掉双引号,这是一个矛盾,解决了这个问题就可以解决了这个难题。
寂寞是黑白的,但黑白不是寂寞,是永恒。BAT 需要的不是可能,而是智慧。

TOP

回复 33# cjiabing

建了个文件,名为 4~@%#$!^&=().jpg,拖进去不行。。。

TOP

顶下

TOP

本帖最后由 幼稚园 于 2012-8-10 09:34 编辑

果然好难啊!
29楼的(abc)&(xyz).txt.txt拖到批处理上,在传递参数时就发生错误了!
潜水学习......

TOP

本帖最后由 cjiabing 于 2012-2-23 00:35 编辑

我弱弱地问,以下代码满足了楼主的要求没有?
首先,用dir来获得文件的路径(我经常用if 、dir、%fa来干这种事),有点罗嗦,对文件夹无效,可惜无法用if exist。
第二、既然%*能保存所有参数,那么把这些含有特殊符号的参数全部输入到dir,而dir是不会对文件进行操作的,所以它也可以保存内容。
第三、for虽然也是逐行逐个处理,遇到特殊符号会发生错误。但对于集合内的命令执行结果它们却视而不见,你可以先ipconfig再for,而不必考虑它输出来的是什么。
  1. @echo off
  2. ::显示所有拖入文件的路径,完美支持楼主提供的含有特殊符号的文件名。唯一不足的是不支持文件夹,文件夹需要另外想办法。
  3. echo     以下是文件:
  4. dir /b %*
  5. pause
  6. ::计算拖入文件的个数,用来验证。
  7. dir /b %*|findstr /n /i .*
  8. pause
  9. @echo off&setlocal enabledelayedexpansion
  10. ::决定还是用FOR来验证,避免无法继续下一步操作。
  11. set num=0
  12. for /f "tokens=*" %%a in ('dir /b %*') do set /a num+=1&echo;!num!:%%a
  13. pause
复制代码
寂寞是黑白的,但黑白不是寂寞,是永恒。BAT 需要的不是可能,而是智慧。

TOP

本帖最后由 cjiabing 于 2011-6-3 13:27 编辑

21# zm900612
忘记怎么说了,从实践总结出来的!~
或许,外面的FOR真的多余了,有空研究清楚了再说说道理!~
寂寞是黑白的,但黑白不是寂寞,是永恒。BAT 需要的不是可能,而是智慧。

TOP

本帖最后由 techon 于 2011-5-10 02:16 编辑

没什么好办法了?。。。

TOP

本帖最后由 techon 于 2011-5-10 01:51 编辑

这个cmd  shell 不给力 改天试试 PowerShell

TOP

为什么不试试这个:
(abc)&(xyz).txt

TOP

本帖最后由 techon 于 2011-5-10 01:45 编辑

原来是这样的。。。只要路径或文件名中有空格 就会加上引号从而处理任何文件名,
路径和文件名都没有空格,但是有特殊符号时 如 & ^ % 等 则会出现错误。。。

怪不得我在桌面上找了一堆文件都没问题呢

TOP

返回列表