批量获取绝对路径的相对路径

Batch get relative path from absolute path

如何批量将绝对路径转换为相对路径?我有一个到目录A和参考目录B的绝对路径,我需要到相对于BA的路径。例如,下面的批处理脚本应该打印..\other\somedir\

1
2
3
4
5
setlocal enabledelayedexpansion
set referencePath=C:\Users\xyz\project\
set absolutePath=C:\Users\xyz\other\somedir\
set relativePath=...
echo %relativePath%

我试过relativePath=!absolutePath:%referencePath%=!,但这是C:\Users\xyz\other\somedir\的绝对路径。

我需要类似于python函数os.path.relpath的东西:

1
2
>>> os.path.relpath("C:\\Users\\xyz\\other\\somedir","C:\\Users\\xyz\\project\")
"..\\other\\somedir"

我需要这个,因为我有一个批处理文件,其中的命令行参数与上面的文件名类似。这个批处理文件创建另一个批处理文件startup.bat,它设置一些环境变量并启动一个应用程序。startup.bat可以通过网络调用,所以我必须使用相对路径。对于绝对路径,环境变量将指向错误计算机上的文件。


这是一个快速的,不肮脏的黑客:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@echo off
setlocal enabledelayedexpansion
set referencePath=C:\Users\xyz\project\
set absolutePath=C:\Users\xyz\other\somedir\
set relativePath=
:LOOP
for /F"tokens=1 delims=" %%a in ("%referencePath%") do (set ref=%%a)
for /F"tokens=1 delims=" %%a in ("%absolutePath%") do (set rel=%%a)
if /i !ref!==!rel! (
    set referencePath=!referencePath:%ref%\=!
    set absolutePath=!absolutePath:%rel%\=!
    goto LOOP
)
:RELLOOP
for /F"tokens=1 delims=" %%a in ("%absolutePath%") do (
    set absolutePath=!absolutePath:%%a\=!
    set relativePath=!relativePath!..\
)
if not"%absolutePath%"=="" goto RELLOOP
set complRelPath=%relativePath%%referencePath%
echo !complRelPath!

如果文件夹位于不同的驱动器上,这不会给您提供propper输出,因此您必须自己处理这个特殊情况。

编辑(评论):好吧,这不可能是那么困难,你自己无法解决。如果/\是混合的(这是个坏主意——我们在窗户上!Windows意味着在路径中,Unix等意味着/在路径中),您应该替换/替换为:

1
2
SET referencePath=%referencePath:/=\%
SET absolutePath=%absolutePath:/=\%

如果路径相等,则无需执行任何操作:

1
2
3
4
IF %referencePath%==%absolutePath% (
    SET complRelPath=.\
    GOTO WHATEVER
)


…以及一个利用PowerShell的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Echo Off
Set"referencePath=C:\Users\xyz\project"
Set"absolutePath=C:\Users\xyz\other\somedir"
Set"relativePath="
Set"_="
If /I Not"%CD%"=="%referencePath%" (Set"_=T"
    PushD"%referencePath%" 2>Nul || Exit /B)
For /F"Delims=" %%A In ('
    PowerShell -C"Resolve-Path -LiteralPath '%absolutePath%' -Relative"
') Do Set"relativePath=%%A"
If Defined _ PopD
If Defined relativePath Echo %relativePath%
Pause

这显然只适用于实际的现有路径


虽然我完全理解你想做什么,但我不喜欢这种方法。

相反,为什么不使用您的环境路径,我们将在其中搜索路径中的相关文件。

1
2
3
@echo off
for %%g in ("bin\startup-batch.cmd") do @set"pathTobat=%%~$PATH:g"
echo"%pathTobat%"

1
2
3
4
5
6
7
8
9
10
11
@ECHO OFF
setlocal enabledelayedexpansion
set referencePath=C:\Users\xyz\project\
set absolutePath=C:\Users\xyz\other\somedir\
FOR %%a IN ("%absolutepath%") DO FOR %%r IN ("%referencepath%.") DO (
 SET"abspath=%%~pa"
 SET"relativepath=!abspath:%%~pr=..\!"
)
echo %relativePath%

GOTO :EOF

如果你告诉我们你想要的输出是什么,那将是有帮助的。告诉我们您当前代码的输出是什么,而这并不是您所期望的,那么如何使用其他平台获得某些东西并没有特别的帮助。

问题是,您正试图在包含冒号的字符串中替换包含冒号的字符串。cmd`很困惑,因为它不知道三个冒号中哪个是哪个。

此解决方案是不受限制的,因为它假定要删除的路径部分正好是EDOCX1的父目录(0)。在缺乏更多信息的情况下,据我猜测…