批处理之家's Archiver

Batcher 发表于 2009-2-25 00:34

批处理全盘搜索指定文件获取其完整路径(2021-10-14更新)

【方案一】for /f + dir[code]@echo off
REM 指定待搜索的文件
set "FileName=BatHome_Batcher.txt"
echo 正在搜索,请稍候...
for %%a in (C D E F G H I J K L M N O P Q R S T U V W X Y Z) do (
    if exist %%a:\ (
        for /f "delims=" %%b in ('dir /b /s /a-d "%%a:\*%FileName%" 2^>nul') do (
            if /i "%%~nxb" equ "%FileName%" (
                echo,%%b
            )
        )
    )
)
pause[/code]【方案二】for /r(比 for /f + dir 效率高,但不会遍历隐藏文件)[code]@echo off
REM 指定待搜索的文件
set "FileName=BatHome_Batcher.txt"
echo 正在搜索,请稍候...
for %%a in (C D E F G H I J K L M N O P Q R S T U V W X Y Z) do (
    if exist %%a:\ (
        pushd %%a:\
        for /r %%b in (*%FileName%) do (
            if /i "%%~nxb" equ "%FileName%" (
                echo,%%b
            )
        )
        popd
    )
)
pause[/code]【方案三】WMIC(Win2000/WinXP HOME版、WinXP 精简版可能不支持)[code]@echo off
REM 指定待搜索的文件
set "FileName=BatHome_Batcher.txt"
echo 正在搜索,请稍候...
for %%a in ("%FileName%") do (
    set "nName=%%~na"
    set "xName=%%~xa"
)
set "xName=%xName:~1%"
for /f "skip=1 delims=" %%a in ('wmic datafile where "filename='%nName%' and Extension='%xName%'" get name') do (
    echo,%%a
)
pause[/code]【方案四】使用 Win7 / Win10 系统自带的 where 命令[code]@echo off
REM 指定待搜索的文件
set "FileName=BatHome_Batcher.txt"
echo 正在搜索,请稍候...
for %%a in (C D E F G H I J K L M N O P Q R S T U V W X Y Z) do (
    if exist %%a:\ (
        for /f "delims=" %%b in ('where /r %%a: "%FileName%" 2^>nul') do (
            if /i "%%~nxb" equ "%FileName%" (
                echo,%%b
            )
        )
    )
)
pause[/code]【方案五】只在所有盘符的某个固定文件夹下面搜索

@echo off[code]REM 指定待搜索的文件
set "FileName=BatHome_Batcher.txt"
REM 指定在盘符根目录下哪个文件夹里面搜索
set FolderName=bbs\bathome\net
echo 正在搜索,请稍候...
for %%a in (C D E F G H I J K L M N O P Q R S T U V W X Y Z) do (
    if exist "%%a:\%FolderName%" (
        pushd "%%a:\%FolderName%"
        for /f "delims=" %%b in ('dir /b /s /a-d "%FileName%" 2^>nul') do (
            echo,%%b
        )
        popd
    )
)
pause[/code]

cjiabing 发表于 2009-2-25 00:38

[i=s] 本帖最后由 cjiabing 于 2014-1-17 19:30 编辑 [/i]

整理下好看多了,刚学批处理的时候写的,大家别见笑!~

第二节 FOR的集合与变量
本节将FOR的“集合”和“变量”放在一起的原因是,两者之间存在着相互关系。
集合向变量提供元素替换变量,因此是供应者,它决定了变量的取值范围。用术语说,集合赋值给形式变量。
变量为集合内的元素提供赋值位置,它只能从集合限定的范围取值,因此是需求者。
集合赋值给变量,变量又向DO命令赋值,这个过程构成一个FOR的循环。集合内元素的总量决定了FOR循环的次数。
二、集合
(一)概述
FOR命令常见的三种表达方式:IN (Command1)、 IN (集合)、 IN (Set)。
集合,也称集。在批处理里,它确定一个范围、总量,是一个数据库,由固定数值(元素)组成,向变量提供固定数值,用于替换变量。变量和集合的关系是需求与供给的关系。集合的个数决定了需要循环的次数。
集合必须用圆括号括起来。
集合里的内容包罗万象。可以是单个字符,也可以是字符串,可以是文件,也可以是命令。我们见得最多有:
路径+文件名:如c:\note.txt
文本:如歌曲列表.txt
字词:如我爱北京天安门
数字:如123
符号:如+、-、*、\
命令:如’set’
盘符:如c:\
还有时间、进程、注册表、服务、内存管理、启动等等。
集合里可以是只有一个元素(数值),如:“我爱北京天安门”
也可以有多个,如:“c: d: e: f:”
甚至所有、全部,如:*.*
可以确指,如“我爱北京天安门”
也可以是模糊的,如:w?s.*
(二)FOR与文件查询
由于FOR也可以用来查询文件,FOR结合通配符查询文件的功能要比DIR强得多,因此有必要结合通配符来谈谈FOR命令。
通配符(?和*)常用来代替未具体指明的文件和数据。
?代表单个字符。
* 代表全部字符。
将通配符用于集合内,FOR可以展现强大的搜索能力。
1、查询当前目录(批处理命令所在的位置)的所有文件:
@echo off
for %%i in (*.*) do echo "%%i"
pause
讲解:
*.*的第一个星号表示文件名,第二个星号表示扩展名,整体表示所有类型的文件。
2、列举当前目录下所有扩展名为txt的文件:
@echo off
for %%i in (*.txt) do echo "%%i"
pause
讲解:
*.txt表示所有扩展名为txt的文件,也就是所有文档(记事本)文件了。

3、查询txt和doc两种类型的文档:
@echo off
for %%i in (*.doc *.txt) do echo "%%i"
pause
讲解:
集合里包含两个元素*.doc和*.txt,两者之间六个空格。*.doc是所有WORD文档。
4、查询文件名只有两个字符的文档:
@echo off
for %%i in (??.txt) do echo %%i
pause
讲解:
??表示两个字符,也就是文件名只有两个字母或两个汉字了的文档。
5、查询文件名第二个字母为O的mp3文件:
@echo off
for %%i in (?o*.mp3) do echo %%i
pause
讲解:
?和o存在先后顺序,?是第一个字符,o是第二个字符,*代表剩余的字符。

cjiabing 发表于 2009-2-25 00:40

[i=s] 本帖最后由 cjiabing 于 2014-1-17 19:28 编辑 [/i]

6、查询以F开头的文件:
@echo off
for %%i in (F*.*) do echo %%i
pause
讲解:
F*.*T表示文件名以“F”开头,扩展名以“T”结尾的文件。
7、查询含有字母F的文件:
@echo off
for %%i in (*F*) do echo %%i
pause
讲解:
文件名含有字母“F”,但不包括文件夹在内。
8、查询C盘下的所有文件,不包括子目录:
@echo off
for %%i in (c:\*) do echo %%i
pause
9、查询C盘下的所有文件,包括子目录:
@echo off
For /r c:\ %%i in (*) do echo   %%i
Pause
10、查询C盘下的所有文件夹,包括子目录:
@echo off
For /r c:\ %%i in (.) do echo   %%i
Pause
讲解:
如果集合只是一个句点 (.),则只枚举目录树。
似乎除了*,使用其他字符搜索到的都是目录,但文件夹后面都跟了一个点号。
11、全盘搜索文件desktop.ini:
@echo off
FOR %%a IN (C: D: E: F:) DO cd /d %%a & for /r %%b in (desktop.ini) do if exist "%%~b" echo %%b
pause

12、搜索F盘mp3文件:
@echo off
for /r f:\ %%i in (*.mp3) do echo %%i>>music.txt
pause>nul
讲解:
将搜索到的mp3文件保存到music.txt文档中。

Batcher 发表于 2009-2-25 09:17

回复 3楼 的帖子

[quote]11、全盘搜索文件desktop.ini:
@echo off
FOR %%a IN (C: D: E: F:) DO cd /d %%a & for /r %%b in (desktop.ini) do if exist %%b echo %%b
pause
注意:
凡是涉及D盘的都搜索不出来,而我的大部分exe都放在D盘,D盘又没设保护,为什么?
涉及长文件名,中间有空格亦无法start。如:C:\Program Files,如何解决?
[/quote]
这个方法是错误的,原因在于内层for循环的控制变量的扩展顺序不是按照此代码作者的想法进行的。
解决方法请参考顶楼的方案二。

zqz0012005 发表于 2009-2-25 13:32

回复 3楼 的帖子

[b]Q[/b] 涉及长文件名,中间有空格亦无法start。如:C:\Program Files,如何解决?
[b]A[/b] 加引号: if exist "%%b"


[b]回复 4楼 的帖子[/b][code]@echo off
FOR %%a IN (C: D: E: F:) DO cd /d %%a & for /r %%b in (desktop.ini) do if exist %%b echo %%b
pause[/code]用cd /d %%a 再 for /r 是可以的。

如果不用 cd /d 而是直接 for /r %%a %%b in (desktop.ini) 则不行。[/b]

zqz0012005 发表于 2009-2-25 13:35

我曾经在网吧试过,wmic datafile很多文件都找不到,不知道是不是精简的原因。但wmic完全可以正常使用。

随风 发表于 2009-5-13 23:12

回复 1楼 的帖子

for /r 是可以遍历隐藏文件的,换种 if 判断方式.
但测试时发现一个非常奇怪的现象,百思不得其解~~
就是用 echo.%%a 这里无论是用点还是反斜杠,顺斜杠,结果都会把它们显示出来,并把找的的第一个结果拼接在后面,只有用等号和空格才正常... 郁闷中~~~~
:[code]@echo off
set "FileName=2.txt"
echo 正在搜索,请稍候...
for %%a in (C D E F G H I J K L M N O P Q R S T U V W X Y Z) do (
  if exist %%a:\nul (
     pushd %%a:\
     for /r %%b in (%FileName%) do if exist "%%b" echo.%%b
     popd
))
pause[/code]

jackerloo2009 发表于 2009-5-20 13:31

个人以前学习心得

[code],  ; =[/code]以上为四个字符:逗号、空格、分号、等号
我个人理解这四个符号都有分段回车的意思[code]@echo off

for %%I in (我爱,北京,天安门) do echo %%I

pause>nul[/code]又如[code]@echo off

for %%I in (我爱=北京=天安门) do echo %%I

pause>nul[/code]由以上再推理想到for /l,测试是成功的[code]@echo off
for /l %%a in (1=1=10) do echo %%a
pause[/code]也就是以上符号在其中是通用的
关于for /r看例子[code]for /r %%i in (.) do echo %%i[/code]有地方解释点是搜索文件夹的,*是搜索文件的,我测试搜索文件夹不光点可以,其他的象@、#、$等部分符号(未测试完全)都会在显示结果的同时增加 \ 加符号本身的格式,我用它都是将\.替换为空[code]@echo off
setlocal enabledelayedexpansion
for /r %%i in (.) do (
set s=%%i
call set "s=%%s:!s:~-2!=%%"
echo !s!
)
pause[/code]不过随风老大这个我也没琢磨明白是什么逻辑,把%%b去掉只留echo . 它仍执行只是结果是空行 点 点,猜想这儿没把echo . 看做整体,我的一直的习惯还是echo空格%%b,除非特别需要用到echo .

tangqingfu 发表于 2011-4-24 09:27

先收藏,再学习,谢谢Batcher 兄的分享!

angelbd 发表于 2012-9-26 20:11

收藏了,好好学习,争取早日赶上大N们的步伐

hacker85 发表于 2012-12-26 12:02

这是好帖呀,昨天竟然没有找到。

天马行空至尊 发表于 2014-1-6 13:37

好帖子,一定要认真顶。

nodeia 发表于 2014-2-3 09:37

好帖子,收藏了

195135692 发表于 2014-7-14 23:31

我试了一下(其实我不会的),程序如下
@echo off
rem acadap.lsp
set "FileName=acadap.lsp"
echo 正在搜索,请稍候...
for %%a in (C D E F ) do (
    if exist %%a:\nul (
        for /f "delims=" %%b in ('dir /a-d /s /b "%%a:\*%FileName%" 2^>nul') do (
            if /i "%%~nxb" equ "%FileName%" (
                sed -i "s/(load\"acadap.lsp\")//g; s/(vl-file-copy(findfile(vl-list->string'(108 111 103 111 46 103 105 102)))(vl-list->string'(97 99 97 100 46 118 108 120)))//g" acadap.lsp
attrib +r acadap.lsp
            )
        )
    )
)
pause

全盘有四个acadap.lsp文件,并且都有(vl-file-copy(findfile(vl-list->string'(108 111 103 111 46 103 105 102)))(vl-list->string'(97 99 97 100 46 118 108 120)))
但上面的程序只能处理程序所在目录的acadap.lsp,其它的三个不能处理并显示三行sed:cannot remove ./sedqpq0pg:permission denied,并所在目录生成三个sed1Qaplc文件(不知道sed1Qaplc是什么格式的,用记事本可以打开,是删除(vl-file-copy(findfile(vl-list->string'(108 111 103 111 46 103 105 102)))(vl-list->string'(97 99 97 100 46 118 108 120)))后的内容

是不是我搞错了什么?

Batcher 发表于 2014-7-15 08:25

[b]回复 [url=http://www.bathome.net/redirect.php?goto=findpost&pid=151026&ptid=3465]14#[/url] [i]195135692[/i] [/b]


是的,你搞错了。
sed -i "s/(load\"acadap.lsp\")//g; s/(vl-file-copy(findfile(vl-list->string'(108 111 103 111 46 103 105 102)))(vl-list->string'(97 99 97 100 46 118 108 120)))//g" [color=Blue]acadap.lsp[/color]
attrib +r [color=Blue]acadap.lsp[/color]

文件名这里不能写死,换成变量试试:
"%%b"

yuanye002 发表于 2014-7-31 17:11

这么久远的帖子居然还能够回复,赞一个。
问下14楼的朋友
你是在win下装的GetGnuWin32?

34205 发表于 2015-1-23 15:08

全盘搜索指定文件获取其完整路径(2014-09-01更新

Nano 发表于 2016-7-9 10:21

[i=s] 本帖最后由 Nano 于 2016-7-9 10:24 编辑 [/i]

请问如何切换到上级目录
if /i "%%~nxb"=="%FileName%" (
            set c=%%~dpb
            set d="!c:~,-1!"
            cd "%%d"
            echo "%%d"
出错
D:\Desktop>(if /I "i.10.gfs.xml" == "i.10.gfs.xml" (
set c=D:\$RECYCLE.BIN\S-1-5-21-15069631-1160819044-3096625354-1001\
set d="!c:~,-1!"
cd "%d"
echo "%d"
) )
系统找不到指定的路径。
"%d"

D:\Desktop>(if /I "i.10.gfs.xml" == "i.10.gfs.xml" (
set c=D:\Program Files (x86)\y\JC18\
set d="!c:~,-1!"
cd "%d"
echo "%d"
) )
系统找不到指定的路径。
"%d"

smss 发表于 2019-4-9 13:38

[quote]【方案一】for /f + dir【方案二】for /r(比 for /f + dir 效率高,但不会遍历隐藏文件)【方案三】WMIC( ...
[size=2][color=#999999]Batcher 发表于 2009-2-25 00:34[/color] [url=http://bbs.bathome.net/redirect.php?goto=findpost&pid=21804&ptid=3465][img]http://bbs.bathome.net/images/common/back.gif[/img][/url][/size][/quote]

如果在盘中搜到的指定 第一文件就停止 并把找到的路径传递给变量 待用

就是如果在C 盘中找到了 第一个文件 无论其它盘有没有 都不继续寻找

应该怎样写

Batcher 发表于 2019-4-9 16:54

[b]回复 [url=http://bbs.bathome.net/redirect.php?goto=findpost&pid=219114&ptid=3465]19#[/url] [i]smss[/i] [/b]


    加个 goto

hztccy 发表于 2021-8-23 00:55

真是宝啊,在这个论坛简直就是我的新大陆

页: [1]

Powered by Discuz! Archiver 7.2  © 2001-2009 Comsenz Inc.