2012-11-15 83 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)和相對路徑(..\..\.)。