我有一个脚本,该脚本输出名称以预定义值开头的所有子文件夹。因为我需要它在网络位置上工作,所以我使用PushD。一切正常,输出符合请求的搜索条件。但是,当前输出将在临时位置上显示该位置,而不是在netwerk路径上显示完整路径。如何修改脚本以显示正确的完整网络位置,而不是temp文件夹上的位置?我可以搜索并替换吗?
@echo off
set arg1=%1
set arg2=%2
PushD %arg1% &&(
forfiles /s /m %arg2%* /c "cmd /c if @isdir==TRUE echo @path"
) & PopD
所以在跑步时 c:\ test.bat“ \\ server \ folder”演示
将输出...
z:\folder\DEMO_project 1
而不是...
\\server\folder\DEMO_project 1
我该如何解决?谢谢...
答案 0 :(得分:0)
您已经知道UNC路径为\\server\folder
,是否有任何原因导致您不返回@RelPath
?
@If "%~2"=="" Exit /B
@PushD "%~1" 2>NUL&&(
ForFiles /M "%~2*" /S /C "Cmd /C If @IsDir==TRUE Echo @RelPath"
)&PopD&Pause
在这种情况下,返回的输出看起来更像.\folder\DEMO_project 1
。
@If "%~2"=="" Exit /B
@PushD "%~1" 2>NUL&&(
ForFiles /M "%~2*" /S /C "Cmd /Q/C If @IsDir==TRUE For /F \"Tokens=*Delims=.\" %%A In (@RelPath)Do Echo %~1%%~A"
)&PopD&Pause
此示例将返回更多输出,例如\\server\folder\folder\DEMO_project 1
答案 1 :(得分:0)
prompt
command可以显示网络路径,以防驱动器指向网络路径,尽管不幸的是返回了尾随的 SPACE 。无论如何,可以通过以下方式实现:
@echo off
pushd "%~1" && (
forfiles /S /M "%~2*" /C "cmd /Q /C if @isdir==TRUE for /F 0x22tokens=1-3 delims=/0x22 %%A in ('prompt $P\/$M^& for %%z in ^(@relpath^) do rem/%%~z') do if 0x22%%B0x22==0x22rem0x22 (for %%z in (@path) do echo(%%~z) else set 0x22SH=%%B/.\%%~pA rem/%%C0x22 & cmd /V /C echo(!SH: rem/.\=!"
popd
)
为解释forfiles
command的/C
选项背后的代码,将其解析为具有代码块,并将0x22
替换为"
;查看所有附加插入的说明性rem
备注:
rem // Execute the following code only when the current item is a directory:
if @isdir==TRUE (
rem // Capture the following command echo string:
for /F "tokens=1-3 delims=/" %%A in ('
rem/ Set the prompt string, then use a `for` loop that iterates once, ^^
rem/ executes `rem` with the relative path of the current item and ^^
rem/ just echos this with the prompt string preceded: ^& ^^
prompt $P\/$M^& for %%z in ^(@relpath^) do rem/%%~z
') do (
rem // The second token is just `rem` in case we have a local path:
if "%%B"=="rem" (
rem /* Simply echo the full path of the local path, but with the surrounding
rem quotation marks removed by a `for` loop and the `~` modifier: */
for %%z in (@path) do echo(%%~z
) else (
rem /* For a network path, we need to build the absolute UNC path by joining
rem the captured network path from the echo string, the path relative to
rem the drive mapped by `pushd` and the relative path from `forfiles`;
rem // since the echo string also contains the echoed command `rem` itself,
rem let us smartly assemble a string that requires only one replacement: */
set "SH=%%B/.\%%~pA rem/%%C"
rem /* Echo the build absolute network path with two removals of ` rem/.\`;
rem enable delayed expansion at this point to avoid losses of `!`: */
cmd /V /C echo(!SH: rem/.\=!
)
)
)
Delayed expansion对于修改和收集同一行代码中的变量SH
是必需的。
Sub-string substitution然后用于消除因回显命令rem
而产生的伪像。
要详细解释代码的工作原理,让我们假设一些示例情况,并查看带有前面的提示字符串的命令回显以及如何将其拆分和合并:
当前路径D:\
是本地路径,并且有一个匹配的子项目Sub
:
提示符为D:\\/
,回显为rem/.\Sub
,因此for /F
收到了要解析的消息:
D:\\/rem/.\Sub
for /F
将其分为三个令牌D:\\
(%A
)和rem
(%B
)和.\Sub
({ {1}});
第二个标记只是%C
,因此只需返回删除了周围引号的绝对路径即可:
rem
当前路径D:\Sub
是本地路径,并且有一个匹配的子项目D:\Data\Test
:
提示符为Sub
,回显为D:\Data\Test\/
,因此rem/.\Sub
收到了要解析的消息:
for /F
D:\Data\Test\/rem/.\Sub
将其分为三个令牌for /F
(D:\Data\Test\
)和%A
(rem
)和%B
({ {1}});
第二个标记只是.\Sub
,因此只需返回删除了周围引号的绝对路径即可:
%C
当前路径rem
是网络路径,驱动器D:\Data\Test\Sub
指向远程位置Z:\
,并且有一个匹配的子项Z:
:
提示符是\\SERVER\Share
+ SPACE ,回显是Sub
,所以Z:\\/\\SERVER\Share
收到了要解析的消息:
rem/.\Sub
for /F
将其分为三个令牌Z:\\/\\SERVER\Share rem/.\Sub
(for /F
)和Z:\\
(%A
)和\\SERVER\Share rem
({ {1}});
第二个令牌不只是%B
,因此附加.\Sub
,然后删除驱动器%C
的第一个令牌(因此,rem
如旧的{ {1}}修饰符将/.\
解析为Z:
),然后是 SPACE + \
,然后是第三个标记,因此得到以下字符串:
~p
在删除了子字符串 SPACE 的两个实例之后,我们最终得到:
\\
当前路径\
是网络路径,驱动器rem/
指向远程位置\\SERVER\Share rem/.\\ rem/.\Sub
,并且有一个匹配的子项\\SERVER\Share\Sub
:
提示符是Z:\Test
+ SPACE ,回显是Z:
,所以\\SERVER\Share
收到了要解析的消息:
Sub
Z:\Test\/\\SERVER\Share
将其分为三个令牌rem/.\Sub
(for /F
)和Z:\Test\/\\SERVER\Share rem/.\Sub
(for /F
)和Z:\Test\
({ {1}});
第二个令牌不只是%A
,所以附加\\SERVER\Share rem
,然后附加第一个令牌,并删除驱动器%B
(因此删除.\Sub
),然后< kbd> SPACE + %C
,然后是第三个标记,因此我们得到以下字符串:
rem
在删除了子字符串 SPACE 的两个实例之后,我们最终得到:
/.\