在批处理文件中将绝对路径转换为相对路径

7

在批处理文件中,是否有可能将绝对路径转换为相对路径?(与此问题的相反情况)。显然,您需要两个输入:要转换的绝对路径和要相对化的绝对参考路径。

例如:

Path to convert: c:\documents\mynicefiles\afile.txt
Reference path:  c:\documents
Result:          mynicefiles\afile.txt
3个回答

6
@echo off
setlocal EnableDelayedExpansion
set Path_to_convert=c:\documents\mynicefiles\afile.txt
set Reference_path=c:\documents
set Result=!Path_to_convert:*%Reference_path%\=!
echo Result: %Result%

谢谢,看起来完美无缺!我以前从未见过这种语法,请问您能提供一下解释或链接吗? - David Cook
我也点赞了,因为它有效,尽管我不想承认,但我不知道为什么。 - Mike Nakis
输入命令 SET /? 并查找以下内容的解释: "环境变量替换已经增强,如下所示:%PATH:str1=str2%" 以及 "延迟环境变量扩展允许您..." - Aacini
2
当脚本中的路径不是硬编码而是从%CD%或FOR变量中获取时,似乎无法正常工作。 :( - MarioVilas

0
以下是一个“dostips”解决方案。
操作级别相当晦涩,但非常高效!

*标题中提供的示例应该有助于理解此宏的用法。

::=//////////////////////////////////////////////////////////////////////////
::= Makes a file name relative to a base path.
::= *param-1:  file [in,out]  - variable with file name to be converted, or file name itself for result in stdout
::= *param-2:  base [in,opt*] - base path | *leave blank for current directory
::= *return:   The resolved relative path is stored into *param-1
::=
::= SAMPLE*HOW-TO-USE:
::=  a) Current path       =D:\titi\toto\
::=  b) DATAPATH_absolute  =D:\titi\tata\tutu\log.txt
::=  c) --relativize the data-path--
::=
::=    c1) INIT the data:
::=        $>  set DATAPATH_relative=%DATAPATH_absolute%
::=
::=    c2) CALL the sub-function:
::=        $>  call  :MakeRelative  DATAPATH_relative
::=
::=    c3) (( After the call, result is set in %DATAPATH_relative% ))
::=
::=  d) echo DATAPATH_relative =%DATAPATH_relative%
::=                     /--->   "..\tata\tutu\log.txt"
::=
::= $source https://www.dostips.com
::= **web:  https://www.dostips.com/?t=Function.MakeRelative
::= **web:  https://www.dostips.com/DtCodeCmdLib.php#Function.MakeRelative
::=--------------------------------------------------------------------------

:MakeRelative
    SETLOCAL ENABLEDELAYEDEXPANSION

    set src=%~1
    if defined %1 set src=!%~1!
    set bas=%~2
    if not defined bas set bas=%cd%

    for /f "tokens=*" %%a in ("%src%") do set src=%%~fa
    for /f "tokens=*" %%a in ("%bas%") do set bas=%%~fa
    set mat=&rem variable to store matching part of the name
    set upp=&rem variable to reference a parent

    for /f "tokens=*" %%a in ('echo.%bas:\=^&echo.%') do (
        set sub=!sub!%%a\
        call set tmp=%%src:!sub!=%%
        if "!tmp!" NEQ "!src!" (set mat=!sub!) ELSE (set upp=!upp!..\)
    )

    set src=%upp%!src:%mat%=!
    ( ENDLOCAL & REM RETURN VALUES
        IF defined %1 (SET %~1=%src%) ELSE ECHO.%src%
    )
    EXIT /b

DosTips.com, :MakeRelative

的意思是将链接指向 DosTips.com 网站的 MakeRelative 页面。

0

这里有另一种方法,如果您想从字符串开头删除%cd%,它也可以起作用。它比较慢,但是如果您的情况允许,您可以减少循环次数。

call :removeCommonAtStart outvar C:\Users\Public\Documents\ASUSAccess

:removeCommonAtStart
:: Description: loops through two strings and sets new variable representing unique data
:: Required parameters:
:: name - name of the variable to be returned
:: test - string to have common data removed from start
:: Optional parameters:
:: remove - string if not defined then use %cd% as string.
:: Required functions:
:: removelet
set name=%~1
set test=%~2
set remove=%~3
if not defined remove set remove=%cd%
set endmatch=
FOR /L %%l IN (0,1,150) DO if not defined notequal call :removelet
goto :eof

:removelet
:: Description: called by removeCommonAtStart to remove one letter from the start of two string variables
:: Required preset variables:
:: test
:: remove
:: name
set test=%test:~1%
set %name%=%test:~1%
set remove=%remove:~1%
if "%test:~0,1%" neq "%remove:~0,1%" set notequal=on&exit /b
goto :eof

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接