我使用代码根据相对路径和/或文件名解析绝对路径为了从相对路径中提取绝对路径。
然而,我的问题是如何提取文件夹在树上但级别未知的相对/绝对路径。
假设以下文件夹树(是否有工具可以生成这些?):
- SomeFolder
---- FolderA
------------ FolderAA
------------ FolderAB
---- FolderB
------------ FolderBA
---------------- FolderBAA
---------------- FolderBAB
------------ FolderBB
---------------- FolderBBA
-------------------- FolderBBAA
-------------------- FolderBBAB
---------------- FolderBBB
所以我在,,FolderBBAA
或FolderBAA
。FolderAA
我
在的绝对路径之后FolderA
。
所以我正在寻找一个批处理函数,它会沿着树向上(只向上,不会向下)直到找到由给定名称命名的文件夹,然后将绝对文件夹返回到该文件夹。
如何为批处理文件编写这样的函数?
评论:请注意,查找的文件夹可能不是文件夹路径的一部分pwd
。因此,在每个级别,该函数都应查找该级别的文件夹(但不查找其中的内容)。
伪代码
function [ relPathToFolder ] = SearchFolder( targetFolderName )
relPathToFolder = "None"; %<! Or any other value for the case not found
currFolder = "./";
% If in the currecnt working folder
currFolderItems = dir();
if targetFolderName in currFolderItems
relPathToFolder = currFolder + targetFolderName;
return;
end
% Going up until it is found
while(currFolder is not root)
currFolder = relPathToFolder + "../";
currFolderItems = dir(currFolder)
if targetFolderName in currFolderItems
relPathToFolder = currFolder + targetFolderName;
return
end
% If not found returning the not found string
end
答案1
我更新了答案,现在它还会在父文件夹和子文件夹的子文件夹中进行搜索。MaxLevel 是父文件夹的分隔符,这意味着不要比“父文件夹”更深
例如,如果您输入“Folder_F”并想要搜索名为“我的文件夹”的文件夹,而 MaxLevel 是“桌面”。它只会搜索“我的文件夹”直到桌面及其子文件夹,如果文件夹不存在,则返回“未找到”。MaxLevel 的原因是为了避免搜索时间过长,搜索时间可能包括整个驱动器等。
“C:\用户\ricar\桌面\文件夹_A\文件夹_B\文件夹_C\文件夹_D\文件夹_E\文件夹_F”
搜索存储在名为 GetParent 的函数中,因此您可以调用 Getparent。
@echo off
setLocal EnableDelayedExpansion
for /f %%a in ('"prompt $H&for %%b in (1) do rem"') do set "BS=%%a"
mode con: cols=120 Lines=15
echo.
IF /i exist "%~1" (set "CurrentPath=%~1") else (set /p "CurrentPath=%BS% Please input the Path you want to verify: ")
:Start
set RelPath=
set RelPath2=
set Parent=
set AbsPath=
cls
echo.
echo Current Path Analysed: "%CurrentPath%"
echo.
set /p "Parent=%BS% Please Input the Parent Folder: "
echo.
IF not Defined MaxLevel set /p "MaxLevel=%BS% Please Input Max Level Folder: "
pushd "%CurrentPath%"
Call :GetParent
:GetParent
cls
echo.
echo Current Path Analysed: "%CurrentPath%"
echo.
echo Searching for: "%Parent%"
echo.
echo Max Level: "%Maxlevel%"
echo.
echo Currently Scanning: "%CD%"
for /f "delims=" %%a in ('dir /s /b /ad ^&echo %CD%') do (
IF /i "%CD:~-1%"=="\" (
echo.
Echo Parent Folder not Found^^!
echo.
pause > nul | set /p="%BS% Press any key to continue..."
goto :End
)
IF /i "%%~nxa"=="%Parent%" (
set "AbsPath=%%~dpnxa"
set "RelPath=!RelPath!"
set "RelPath2=!AbsPath:%CD%=!"
IF /i "!RelPath2!"=="" set "RelPath2=%%~nxa"& set "RelPath=..\!RelPath!"
set "RelPath=!RelPath!!RelPath2!"
set "RelPath=!RelPath:\\=\!"
echo.
echo Relative path: "!RelPath!"
echo Absolute path: "!AbsPath!"
echo.
pause > nul | set /p="%BS% Press any key to continue..."
goto :End
)
IF /i "%%~nxa"=="%Maxlevel%" (
echo.
Echo Parent Folder not Found^^!
echo.
pause > nul | set /p="%BS% Press any key to continue..."
goto :End
)
)
cd ..
set "RelPath=..\%RelPath%"
goto :GetParent
:End
echo.
echo.
set /p "Repeat=%BS% Go Again? (y) (n): "
If "%Repeat%"=="y" goto :Start
exit
答案2
您可以使用解析器的工作方式将当前文件夹(%cd%
)“拆分”为所需的基本路径并“注释掉”其余部分:
set folder=%cd:\SomeFolder\=\SomeFolder&REM %
echo %folder%
运行它来echo off
观看“魔术”发生。
阅读输出set /?
以了解子字符串替换的工作原理。
如果somefolder
未找到,则不替换任何内容并返回当前工作文件夹。
编辑
我希望这次我理解正确了:
@echo off
setlocal
pushd "%~dp0"
:loop
dir /ad "%~nx1" >nul 2>&1&& goto :found
if "%cd:~3,1%" == "" echo not found & goto :eof
cd ..
set "rel=..\%rel%"
goto :loop
:found
set "found=%cd%\%~nx1"
echo absolute folder is "%found:\\=\%"
echo relative folder is "%rel%%~nx1"
popd
pause
查看是否FolderA
是当前文件夹的子文件夹。如果不是,则向上移动一个文件夹并重复。如果您位于驱动器的根目录 ( ) 并且仍未找到它,则
中断循环。X:\
必须用 替换,因为\\
它在根部给出了尾随反斜杠,但在其他任何地方都没有。\
%CD%
搜索到的文件夹作为批处理文件的参数(也可以将其拖放到批处理文件上)。
答案3
/* EDIT
所以我正在寻找一个批处理函数...
以下是该版本的说明,认真回答,但假设我只会使用一次,您也可以那样使用它......
rem :: Your code where it is necessary to
rem :: find/define the folder in the variable %_dir%, add:
set^ "_up=..\"
set^ "_cd=FolderA"
%:^(
for /d /r %_up% %%i in =;(*
=;)do if /i "%%~nxi" == "%_cd%" =;(
set^ "_dir=%%~fi" && goto %:^)
=;)
=;<con: set^ "_up=%_up%..\" && goto %:^(
rem :: Your code where you continue from
rem :: that point using the variable %_dir%
*/ EDIT
%:^/
set^ "_up=..\"
%:^(
for /d /r %_up% %%i in =;(*
=;)do if /i "%%~nxi" == "%~nx1" =;(
set "_dir=%%~fi" && goto %:^)
=;)
call set^ "_up=%_up%..\" && goto %:^(
- 上面的函数使用循环来查找文件夹
"FolderA"
,并定义_dir
在参数中传递的文件夹的完整路径%~1
,在:call %:^/ "FolderA"
..
@echo off
rem :: actual bat code ::
rem :: actual bat code ::
rem :: ............... ::
rem :: final code in your bat code ::
rem :: if using setlocal, endlocal ::
endlocal & exit /b || goto :eof
rem :: its function starts below
rem :: just call function "folderName"
rem :: call %:^/ ["Folder_Name_To_Find"]
%:^/
set^ "_up=..\"
%:^(
for /d %%i in =;(%_up%*
=;)do if /i "%%~nxi" == "%~nx1" =;(
cd /d "%%~dpnxi" && goto %:^)
=;)
call set^ "_up=%_up%..\" && goto %:^(
%:^)
echo\Here I'm %CD% & exit /b
1.在 var for 循环中将其..\
(相对路径)定义为字符串,并在找不到文件夹名称后增加:_up
for /d ()
set^ "_up=..\"
for /Directory loop in (..\)
next loop in (..\..\)
next loop in (..\..\..\)
next loop in (so on...)
call set^ "_up=%_up%..\" ==> ..\ + ..\
2.%1
函数名称的参数是%~nx1
,如果名称与当前文件夹名称匹配%%~nxi
1, 你是“要走了” goto %:^)
2...
if /i "%%~nxi" =="%~nx1" =;(
cd /d "%%~dpnxi" && goto %:^)
观察:1甚至寻找文件夹~Name
仅,使用循环文件会扩展%~nxi
到名称 + 扩展名,但当涉及到循环文件夹,建议……
观察:2您也可以在此时退出函数...将此代码替换为exit /b
..)do if /i "%%~nxi" == "%~nx1" =;(
cd /d "%%~dpnxi" && goto %:^) exit /b
=;)
call set^ "_up=%_up%..\" && goto %:^(
%:^)
echo\Here I'm %CD% & exit /b
- 常规布局:
@echo off
rem :: actual bat code ::
rem :: actual bat code ::
rem :: ............... ::
rem :: final code in your bat code ::
rem :: if using setlocal, endlocal ::
endlocal
exit /b || goto :eof
rem :: its function starts below
rem :: just call function "folderName"
rem :: call :main_loop ["Folder_Name_To_Find"]
:main_loop
set "_up=..\"
:loop_folder
for /d %%i in (%_up%*) do (
if /i "%%~nxi" == "%~nx1" (
cd /d "%%~dpnxi"
goto :loop_out
)
)
call set "_up=%_up%..\"
goto :loop_folder
:loop_out
echo\Here I'm %CD%
exit /b
向循环中添加递归:
FOR /R - Loop through files (recursively) FOR /D - Loop through several folders/directories
The option /D /R is undocumented, but can be a useful combination, while it will recurse through all subfolders the wildcard will only match against Folder/Directory names (not filenames) Note: Source linked to ss64.com
...
%:^/
set^ "_up=..\"
%:^(
for /d /r %_up% %%i in =;(*)do if "%%~nxi"=="%~nx1" =;(
cd /d "%%~fi" && set "_dir=%%~fi" && goto %:^)
=;)
call set^ "_up=%_up%..\" && goto %:^(
%:^)
echo\Here I'm %CD%
...
:main_loop
set "_up=..\"
:loop_folder
for /d /r %_up% %%i in (*) do (
if /i "%%~nxi" == "%~nx1" (
cd /d "%%~dpnxi"
set "_dir=%%~fi"
goto :loop_out
)
)
call set "_up=%_up%..\"
goto :loop_folder
:loop_out
echo\Here I'm %CD%
exit /b