【问题标题】:Replace path of the working directory to UNC path将工作目录的路径替换为 UNC 路径
【发布时间】:2019-07-17 10:39:56
【问题描述】:

我有一个脚本,它输出名称以预定义值开头的所有子文件夹。因为我需要它在网络位置上工作,所以我使用 PushD。一切正常,输出符合请求的搜索条件。但是,当前输出显示临时位置上的位置,而不是网络路径上的完整路径。如何修改脚本以显示正确的完整网络位置,而不是临时文件夹上的位置?我可以进行搜索和替换吗?

@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

我该如何解决这个问题?谢谢...

【问题讨论】:

  • 它将分配一个驱动器号供您使用,类似于 net use * \\.. 。您可以只获取驱动器号的 UNC 路径.. 例如,如果您不再使用 forfiles 进行一些更改,那么您可以收集驱动器号并替换为路径.. 例如:for /f "tokens=3" %%i in ('net use ^| findstr /i Z:') do echo %%i跨度>
  • user10053673,请先阅读What should I do when someone answers my question?,然后再考虑发布的答案之一是否能解决您发布的问题。谢谢。

标签: windows batch-file forfiles


【解决方案1】:

您已经知道 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


请注意,我已经发布了完整的 示例以完全替换您发布的代码,它们不需要任何修改!

【讨论】:

    【解决方案2】:

    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 的伪影。


    为了详细解释代码是如何工作的,让我们假设一些示例情况,看看带有前面提示字符串的命令 echo 以及它是如何拆分和连接的:

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

      • 提示是D:\\/,回显是rem/.\Sub,所以for /F接收解析:

        D:\\/rem/.\Sub
        
      • for /F 将其拆分为三个标记 D:\\ (%A) 和 rem (%B) 和 .\Sub (%C);

      • 第二个标记就是rem,所以只需返回去掉周围引号的绝对路径:

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

      • 提示是D:\Data\Test\/,回显是rem/.\Sub,所以for /F接收解析:

        D:\Data\Test\/rem/.\Sub
        
      • for /F 将其拆分为三个标记 D:\Data\Test\ (%A) 和 rem (%B) 和 .\Sub (%C);

      • 第二个标记就是rem,所以只需返回去掉周围引号的绝对路径:

        D:\Data\Test\Sub
        
    3. 当前路径Z:\是一个网络路径,其中驱动器Z:指向远程位置\\SERVER\Share,并且有一个匹配的子项Sub

      • 提示是Z:\\/\\SERVER\Share + SPACE,回显是rem/.\Sub,所以for /F接收解析:

        Z:\\/\\SERVER\Share rem/.\Sub
        
      • for /F 将其拆分为三个标记 Z:\\ (%A) 和 \\SERVER\Share rem (%B) 和 .\Sub (%C);

      • 第二个令牌不仅仅是rem,所以附加/.\,然后删除驱动器Z:的第一个令牌(因此\作为使用的~p修饰符将\\解析为\ ),然后是SPACE + rem/,然后是第三个token,所以我们得到这个字符串:

        \\SERVER\Share rem/.\\ rem/.\Sub
        
      • 在删除子字符串 SPACE + rem/.\ 的两个实例之后,我们终于得到:

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

      • 提示是Z:\Test\/\\SERVER\Share + SPACE,回显是rem/.\Sub,所以for /F接收解析:

        Z:\Test\/\\SERVER\Share rem/.\Sub
        
      • for /F 将其拆分为三个标记 Z:\Test\ (%A) 和 \\SERVER\Share rem (%B) 和 .\Sub (%C);

      • 第二个令牌不仅仅是rem,所以附加/.\,然后是删除驱动器Z:的第一个令牌(因此\Test\),然后是SPACE + rem/ ,然后是第三个标记,所以我们得到这个字符串:

        \\SERVER\Share rem/.\\Test\ rem/.\Sub
        
      • 在删除子字符串 SPACE + rem/.\ 的两个实例后,我们终于得到:

        \\SERVER\Share\Test\Sub
        

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-27
      • 2014-05-22
      • 1970-01-01
      • 1970-01-01
      • 2011-08-16
      • 1970-01-01
      • 2013-01-23
      相关资源
      最近更新 更多