4

私は理解できない単純な問題を抱えています:特定のファイルを含む親フォルダーを見つけ、その親フォルダーの絶対パスを生成したい-これはバッチスクリプト内で実行する必要があります-powershellなし、いいえパール、パイソンなし...

例として、これが私のディレクトリ ツリーであるとします。

  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。(親フォルダーが複数あってもなくてもかまいません。1 つしかないことを確認します。)

ヘルプは大歓迎です。これに多くの時間が無駄になりました...

注: コードも説明していただければ幸いです。2つの回答が有効な解決策を提供する場合、説明がより適切なものを選択します。

4

4 に答える 4

3

すみません。あなたの質問には、私にははっきりしない点がいくつかあります。

  • root_parent_pathディレクトリツリーで示したように、フォルダがディスクのルートフォルダ内に配置されている場合は、次のように名前の前に円記号を含める必要\root_parent_pathがあります。これが当てはまる場合、結果root_parent_path\dir1は相対パスではなく、ディスクのルートフォルダから次のように開始する絶対パスになります\root_parent_path\dir1。以下のバッチファイルはこの点を想定しており、2番目のパラメータの前に円記号を挿入していることに注意してください。

  • 私が理解しているように、最初のパラメーターで指定されたファイルを含む、2番目のパラメーターで指定されたパスの最初のフォルダーが必要です。このバッチファイルはそれを行います:

編集:このバッチファイルは、2番目のパラメーターで完全修飾パスを受け入れるように変更されました

@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-の質問で、出力として相対パスが必要であると述べ、入力として相対パスを使用した例を示しました。あなたの答えは相対なものではなく、ドライブのない絶対的なものであり、私のプログラムはこの状況を想定していることを指摘しました。入力と出力の両方として絶対パスが必要であるというコメントで答える場合、私はすぐにそれを行いますが、もう答えません...

相対パス管理と絶対パス管理は完全に異なり、ディスクドライブが指定または暗示されている場合にも注意する必要があります。最初の質問に2番目のパラメーターが実際に含まれている場合c:\folder1\folder2\、この点は問題になりません。

編集:2番目のパラメーターでスペースを受け入れる新しいバージョン。

@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"

于 2012-11-16T08:07:48.413 に答える
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

これは、 のような UNC パスでは機能しません。\\server\folder1\folder2また、ドライブ文字だけで構成される相対パスでも機能しませんC:。ただし、それ以外は、絶対パスまたは相対パスで動作するはずです。

于 2012-11-15T12:54:17.587 に答える
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...

それらはすべて、ディスクラベルなしで同じ相対パスを返します。よくわかりませんが、それがあなたが探しているものだと思います。c:\folder1\folder2この編集前の私の投稿では、 から始まる絶対パス ( など) と相対パス ( ..\..\.)が返されroot_parent_pathます。

于 2012-11-18T17:26:50.920 に答える
0

このようなもの?

@echo off
set file=%1
set dir=%2
:LOOP
if exist %dir%\%file% (
setx RESULT_PATH %CD%
) else (
cd..
goto :LOOP
)
于 2012-11-15T11:54:35.827 に答える