2012-11-15 128 views
4

我有一个简单的问题,我无法弄清楚:我想查找包含某个文件的父文件夹,并生成该父文件夹的绝对路径 - 并且需要批处理脚本里面做 - 没有PowerShell中,没有的Perl,Python的无...WIndows批处理脚本找到正确的父文件夹

例子,说这是我的目录树:

root_parent_path 
    dir0 
    dir1 
     file1 
     dir2 
     dir21 
     dir22 
     dir3 
     dir31 
     dir32 

在上面的例子,root_parent_path在形式上c:\folder1\folder2\

结果应该存储在一个环境变量中,比如RESULT_PATH。

所以,如果我调用任何如下:

script.batch file1 root_parent_path\dir1\dir2 
script.batch file1 root_parent_path\dir1\dir2\dir21 
script.batch file1 root_parent_path\dir1\dir3\dir31 

变量RESULT_PATH应设置为root_parent_path\dir1,因为这是一个包含file1父。 (我不关心,如果有更多的则是一个或没有父文件夹 - 我将确保只有一个)

帮助深表感谢,这么多的时间被浪费掉了这个...

注意:如果代码也被解释了,我将不胜感激!如果两个答案提供工作解决方案,我会选择一个更好的解释。

+0

你说你想要一个父文件夹的相对路径whoich建议我''root_parent_path \ dir1 \ dir2'评估为'../'。你能澄清一下吗?否则,'cd root_parent_path'跟着'dir/s file1'应该会给你一个字符串,你可以为你的答案解析... – ZombieSheep

+0

有一些混淆,因为文本说相对路径和例子指出什么可能是绝对的。我现在已经将问题转变为绝对路径,因为大多数答案都是这样。 – zmilojko

+0

@zmilojko如果在'c:\ folder1 \ folder2 \'中找到了一个文件,您希望如何设置'result_path':绝对路径为'c:\ folder1 \ folder2 \'或者没有标签的路径'\ folder1 \ folder2'?或搜索开始的相对路径,例如, '.. \ ..'? – fthiella

回答

3

对不起。在你的问题中有几点我不清楚。

  • 如果root_parent_path是放在磁盘的根文件夹中的文件夹,当你在你的目录树表示,那么它必须包括它的名字前加上反斜杠这样:\root_parent_path,对不对?如果这是真的,那么结果root_parent_path\dir1而不是一个相对路径,但绝对的一个从磁盘的根文件夹开始这样:\root_parent_path\dir1,对吧?请注意,下面的批处理文件假设了这一点,并在第二个参数之前插入了一个反斜杠。

  • 据我所知,你想第一个参数给出的文件中的第二个参数给出的路径中的第一个文件夹。这个批处理文件这样做:

编辑:此批处理文件已被修改的第二个参数

@echo off 
setlocal EnableDelayedExpansion 
rem Get drive from second parameter, given or implied 
for %%a in (%2) do set drive=%%~Da 
rem Extract each partial path from second parameter and search first parameter into it 
set return_path= 
set param2=%2 
rem Delete drive from second parameter, if any 
set param2=%param2:*:=% 
for %%a in (%param2:\= %) do (
    set return_path=!return_path!\%%a 
    if exist %drive%!return_path!\%1 goto continue 
) 
set return_path=PATH NOT FOUND 
:continue 
echo %drive%%return_path% 

记住,这样的结果是绝对路径接受一个完全合格的路径。在你的例子相对路径的结果上面会这些值:

script.batch file1 root_parent_path\dir1\dir2   ->  .. 
script.batch file1 root_parent_path\dir1\dir2\dir21  ->  ..\.. 
script.batch file1 root_parent_path\dir1\dir3\dir31  ->  ..\.. 

请注意,路径中的每个文件夹不能包含空格。如果需要,这可能是固定的。

测试程序,并报告结果...

安东尼

PD - 在你ORIGINAL问题,你说你想要一个相对路径作为输出,并把一个例子用相对路径作为输入。我注意到你的回答不是相对,但是绝对没有驱动器,并且我的程序假设了这种情况。如果你想在你想要绝对路径作为输入和输出的注释回答,我会做立即的,但你不要再回答......

您必须注意的是相对绝对路径管理是完全不同的,如果磁盘驱动器是给定暗示。如果你的第一个问题包含第二个参数,那么这个问题就不会成为问题:c:\folder1\folder2\

编辑:接受第二个参数中的空格的新版本。

@echo off 
setlocal EnableDelayedExpansion 
rem Get drive from second parameter, given or implied 
for %%a in (%2) do set drive=%%~Da 
rem Get second parameter removing enclosing quotes, if any 
set param2=%~2 
rem Delete drive from second parameter (from beggining of path until first colon) 
set param2=%param2:*:=% 
rem Change possible spaces in the path by another character (I used dollar sign) 
rem to avoid separate names with spaces at that point 
set param2=%param2: =$% 
rem ... of course, dollars must be returned back to spaces later 
rem Extract each partial path from second parameter and search first parameter into it 
set return_path= 
for %%a in (%param2:\= %) do (
    set return_path=!return_path!\%%a 
    rem Get back spaces converted into dollars 
    set return_path=!return_path:$= ! 
    rem Enclose file name in quotes (required if path contain spaces) 
    if exist "%drive%!return_path!\%1" goto continue 
) 
set return_path=PATH NOT FOUND 
:continue 
echo %drive%%return_path% 

在这种情况下,使用引号中的路径,如果它包含空格:

script.bat file1 "c:\first dir\second dir\dir1\dir2"

+0

这与我所需要的非常接近,只有'root_parent_path'是完全限定的路径,所以从C:\开始。 FIRST_DIR \ SECOND_DIR ...您能否更新您的答案以反映这一点? – zmilojko

+0

这正是我在答案中所解释的:第二个参数被假定为_absolute_(完全限定的除外驱动器)路径,可能会或可能不会以背lash:'FIRST_DIR \ SECOND_DIR ...'或'\ FIRST_DIR \ SECOND_DIR ...'。如果你还需要在这个路径中插入磁盘驱动器,那么需要做一些小修改... – Aacini

+0

是的,这个小小的修改让我花了几个小时,但仍然没有解决它。任何想法?如何删除驱动器号和冒号 - 如果需要,我甚至可以将它作为单独的参数提供。 – zmilojko

0

这样的事情?

@echo off 
set file=%1 
set dir=%2 
:LOOP 
if exist %dir%\%file% (
setx RESULT_PATH %CD% 
) else (
cd.. 
goto :LOOP 
) 
+0

否。您的代码在循环前需要'cd%2',if必须是'if exists%file%('。但是,如果有多个文件具有给定的名称,则此代码将找到_last_文件树... – Aacini

1

获取父项的绝对路径是微不足道的。

@echo off 
setlocal 
set result_path=%~dp1 

获取父级的相对路径有点棘手。没有内置的方式来批量操纵相对路径。这是我能想到的最简单的解决方案。

@echo off 
setlocal 
for %%F in (":.:%~1\..") do set "result_path=%%~fF" 
set "result_path=%result_path:*:.:=%" 

请注意,上述代码不验证结果的存在。它只是从第一个参数中提供的路径剥离最后一个文件夹名称。

编辑

OK,我想我明白你的要求。给定相对路径:"rel_path_root\child1\child2\child3",请在路径的每个步骤中查找"file1"

所以需要测试如果有以下的存在:

  • "rel_path_root\file1"
  • "rel_path_root\child1\file1"
  • "rel_path_root\child1\child2\file1"
  • "rel_path_root\child1\child2\child3\file1"

下面简单的脚本应该做的伎俩。

@echo off 
setlocal enableDelayedExpansion 

:: Get parameters 
set "file=%~1" 
set "myPath=%~2" 

:: Break myPath into component folders by splitting at \ 
:: For example: "root dir\dir 1\dir 2" --> "root dir" "dir 1" "dir 2" 
set "myPath= "!myPath:\=" "!" " 

:: Eliminate empty folders that result from consecutive or trailing \ 
set "myPath=!myPath:"" =!" 

:: Loop through the folders, building the path back up again. 
:: At each iteration, check if file exists and break if found. 
set "testPath=" 
set "resultPath=" 
for %%F in (!myPath!) do (
    if defined testPath (set "testPath=!testPath!\%%~F") else set "testPath=%%~F" 
    if exist "!testPath!\!file!" (
    set "resultPath=!testPath!" 
    goto :break 
) 
) 
:break 

:: print the result 
set resultPath 

这不会像\\server\folder1\folder2 UNC路径工作,也不会使用相对路径组成的不过是一个驱动器号C:工作。但除此之外,它应该与任何绝对或相对路径一起工作。

+0

这不是问题所在,我不需要父文件夹,但祖先文件夹包含指定的文件。首先,请注意脚本,文件名和开始路径有两个输入值。 – zmilojko

+0

好了,我想我现在明白了,在** EDIT **之后查看我提出的解决方案,更新后的答案为 – dbenham

0

这也可能是一个解决办法:

@echo off 
rem save current dir 
pushd "%cd%" 
rem go to specified folder 
cd "%2" 
:loop 
IF EXIST "%1" (
    rem found existing file 
    call :relative_path return_path "%cd%" 
    goto :end_loop 
) 
rem trying to go to upper dir. if it succedes, cd_prec != cd 
set cd_prec=%cd% 
cd .. 
IF NOT "%cd%" == "%cd_prec%" goto :loop 
set return_path=NOT FOUND 
goto :end_loop 

rem function to extract \folder1\folder2\etc from c:\folder1\folder2\etc 
:relative_path <resultVar> <pathVar> 
set "%~1=%~p2" 
exit /b 
) 

:end_loop 
popd 

echo %return_path% 

你指定的人才能路径是绝对的或相对的,并且它返回找到文件的绝对路径和(如果需要的话)也返回相对于指定目录的路径,并且它支持文件和空格名称。我只是使用基本的命令,但我认为这是你正在寻找的。

C:\Users\user\code\cmd>mkdir c:\folder1\folder2\dir1 
C:\Users\user\code\cmd>copy nul c:\folder1\folder2\dir1\file1 
C:\Users\user\code\cmd>mkdir c:\folder1\folder2\dir1\dir2\dir21 
C:\Users\user\code\cmd>mkdir c:\folder1\folder2\dir1\dir2\dir31 

C:\Users\user\code\cmd>script.cmd file1 c:\folder1\folder2\dir1\dir2\ 
\folder1\folder2\dir1 

C:\Users\user\code\cmd>script.cmd file1 c:\folder1\folder2\dir1\dir2\dir21 
\folder1\folder2\dir1 

C:\Users\user\code\cmd>script.cmd file1 c:\folder1\folder2\dir1\dir2\dir31 
\folder1\folder2\dir1 

C:\Users\user\code\cmd>cd c:\folder1\folder2\dir1\dir2\dir21 
C:\folder1\folder2\dir1\dir2\dir21>script.cmd file1 . 
\folder1\folder2\dir1 

etc... 

他们都返回相同的相对路径,没有磁盘标签,我不知道,但我认为这是你在找什么。我在此编辑之前的帖子将返回从root_parent_path开始的绝对路径(如c:\folder1\folder2)和相对路径(..\..\.)。