将工作目录的路径替换为UNC路径

时间:2019-07-17 10:39:56

标签: windows batch-file forfiles

我有一个脚本,该脚本输出名称以预定义值开头的所有子文件夹。因为我需要它在网络位置上工作,所以我使用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

我该如何解决?谢谢...

2 个答案:

答案 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


如果您确实需要在已知的UNC之前添加前缀,则可以使用另一轮解析来用您的已知字符串替换前导时间段:

@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而产生的伪像。


要详细解释代码的工作原理,让我们假设一些示例情况,并查看带有前面的提示字符串的命令回显以及如何将其拆分和合并:

  1. 当前路径D:\是本地路径,并且有一个匹配的子项目Sub

    • 提示符为D:\\/,回显为rem/.\Sub,因此for /F收到了要解析的消息:

      D:\\/rem/.\Sub
      
    • for /F将其分为三个令牌D:\\%A)和rem%B)和.\Sub({ {1}});

    • 第二个标记只是%C,因此只需返回删除了周围引号的绝对路径即可:

      rem
  2. 当前路径D:\Sub 是本地路径,并且有一个匹配的子项目D:\Data\Test

    • 提示符为Sub,回显为D:\Data\Test\/,因此rem/.\Sub收到了要解析的消息:

      for /F
    • D:\Data\Test\/rem/.\Sub 将其分为三个令牌for /FD:\Data\Test\)和%Arem)和%B({ {1}});

    • 第二个标记只是.\Sub,因此只需返回删除了周围引号的绝对路径即可:

      %C
  3. 当前路径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 的两个实例之后,我们最终得到:

      \\
  4. 当前路径\是网络路径,驱动器rem/指向远程位置\\SERVER\Share rem/.\\ rem/.\Sub ,并且有一个匹配的子项\\SERVER\Share\Sub

    • 提示符是Z:\Test + SPACE ,回显是Z:,所以\\SERVER\Share收到了要解析的消息:

      Sub
    • Z:\Test\/\\SERVER\Share将其分为三个令牌rem/.\Subfor /F)和Z:\Test\/\\SERVER\Share rem/.\Sub for /F)和Z:\Test\({ {1}});

    • 第二个令牌不只是%A,所以附加\\SERVER\Share rem,然后附加第一个令牌,并删除驱动器%B(因此删除.\Sub),然后< kbd> SPACE + %C,然后是第三个标记,因此我们得到以下字符串:

      rem
    • 在删除了子字符串 SPACE 的两个实例之后,我们最终得到:

      /.\