webentwicklung-frage-antwort-db.com.de

Absoluten Pfad vom relativen Pfad und / oder Dateinamen auflösen

Gibt es in einem Windows-Stapelskript eine Möglichkeit, einen absoluten Pfad von einem Wert zurückzugeben, der einen Dateinamen und/oder einen relativen Pfad enthält?

Gegeben:

"..\"
"..\somefile.txt"

Ich brauche den absoluten Pfad relativ zur Batch-Datei.

Beispiel:

  • "somefile.txt" befindet sich in "C:\Foo \"
  • "test.bat" befindet sich in "C:\Foo\Bar".
  • Benutzer öffnet ein Befehlsfenster in "C:\Foo" und ruft Bar\test.bat ..\somefile.txt
  • In der Batch-Datei würde "C:\Foo\somefile.txt" abgeleitet von %1
146
Nathan Taylor

In Batch-Dateien enthält das Argument 0 wie in Standard-C-Programmen den Pfad zum aktuell ausgeführten Skript. Sie können %~dp0 Verwenden, um nur den Pfadteil des 0-ten Arguments (welches das aktuelle Skript ist) abzurufen - dieser Pfad ist immer ein vollständig qualifizierter Pfad.

Sie können den vollständig qualifizierten Pfad Ihres ersten Arguments auch mit %~f1 Ermitteln. Dies gibt jedoch einen Pfad an, der dem aktuellen Arbeitsverzeichnis entspricht. Dies ist offensichtlich nicht das, was Sie möchten.

Persönlich verwende ich in meiner Batch-Datei oft das Idiom %~dp0%~1, Das das erste Argument relativ zum Pfad des ausführenden Batch interpretiert. Es hat jedoch einen Nachteil: Es scheitert kläglich, wenn das erste Argument vollständig qualifiziert ist.

Wenn Sie sowohl relative als auch absolute Pfade unterstützen müssen, können Sie Frédéric Ménez 'Lösung verwenden : Ändern Sie vorübergehend die aktuelles Arbeitsverzeichnis.

Hier ist ein Beispiel, das jede dieser Techniken demonstriert:

@echo off
echo %%~dp0 is "%~dp0"
echo %%0 is "%0"
echo %%~dpnx0 is "%~dpnx0"
echo %%~f1 is "%~f1"
echo %%~dp0%%~1 is "%~dp0%~1"

rem Temporarily change the current working directory, to retrieve a full path 
rem   to the first parameter
pushd .
cd %~dp0
echo batch-relative %%~f1 is "%~f1"
popd

Wenn Sie dies als c:\temp\example.bat speichern und von c:\Users\Public als ausführen

c:\Users\Public>\temp\example.bat ..\windows

... Sie werden die folgende Ausgabe beobachten:

%~dp0 is "C:\temp\"
%0 is "\temp\example.bat"
%~dpnx0 is "C:\temp\example.bat"
%~f1 is "C:\Users\windows"
%~dp0%~1 is "C:\temp\..\windows"
batch-relative %~f1 is "C:\Windows"

die Dokumentation zu den Modifikatoren, die für ein Batch-Argument zulässig sind, finden Sie hier: https: //docs.Microsoft.com/en-us/windows-server/administration/windows-commands/call =

152
Adrien Plisson

Ich bin heute Morgen auf ein ähnliches Bedürfnis gestoßen: Wie man einen relativen Pfad in einen absoluten Pfad innerhalb eines Windows-Befehlsskripts umwandelt.

Folgendes hat den Trick getan:

@echo off

set REL_PATH=..\..\
set ABS_PATH=

rem // Save current directory and change to target directory
pushd %REL_PATH%

rem // Save value of CD variable (current directory)
set ABS_PATH=%CD%

rem // Restore original directory
popd

echo Relative path: %REL_PATH%
echo Maps to path: %ABS_PATH%
139

Die meisten dieser Antworten scheinen verrückt nach komplizierten und super Buggys zu sein, hier ist meine - es funktioniert mit jeder Umgebungsvariablen, nein %CD% oder PUSHD/POPD oder for /f Quatsch - einfach nur alte Batch-Funktionen. - Das Verzeichnis und die Datei müssen nicht einmal existieren.

CALL :NORMALIZEPATH "..\..\..\foo\bar.txt"
SET BLAH=%RETVAL%

ECHO "%BLAH%"

:: ========== FUNCTIONS ==========
EXIT /B

:NORMALIZEPATH
  SET RETVAL=%~dpfn1
  EXIT /B
80
BrainSlugs83

Ohne dass Sie eine weitere Batch-Datei benötigen, um Argumente zu übergeben (und die Argumentoperatoren zu verwenden), können Sie FOR /F Verwenden:

FOR /F %%i IN ("..\relativePath") DO echo absolute path: %%~fi

dabei ist i in %%~fi die unter /F %%i definierte Variable. z.B. Wenn Sie dies in /F %%a ändern, wäre der letzte Teil %%~fa.

Um dasselbe direkt an der Eingabeaufforderung (und nicht in einer Batch-Datei) zu tun, ersetzen Sie %% Durch % ...

35
Peter Ritchie

Dies soll dazu beitragen, die Lücken in Adrien Plissons Antwort zu schließen (die sofort nach der Bearbeitung geändert werden sollte ;-):

Sie können den vollständig qualifizierten Pfad Ihres ersten Arguments auch mit% ~ f1 ermitteln. Dies gibt jedoch einen Pfad an, der dem aktuellen Pfad entspricht. Dies ist offensichtlich nicht das, was Sie möchten.

ich weiß leider nicht, wie ich die 2 zusammenmischen soll ...

Mit %0 Und %1 Kann man ebenfalls umgehen:

  • %~dpnx0 Für vollständig qualifiziertes Laufwerk + Pfad + Name + Erweiterung der Batchdatei selbst,
    %~f0 Reicht ebenfalls aus;
  • %~dpnx1 Für vollständig qualifiziertes Laufwerk + Pfad + Name + Erweiterung des ersten Arguments [wenn das überhaupt ein Dateiname ist],
    %~f1 Reicht ebenfalls aus;

%~f1 Funktioniert unabhängig davon, wie Sie Ihr erstes Argument angegeben haben: mit relativen Pfaden oder mit absoluten Pfaden (wenn Sie die Dateierweiterung bei der Benennung von %1 Nicht angeben, wird sie nicht hinzugefügt.) auch wenn Sie %~dpnx1 verwenden - jedoch.

Aber wie um alles in der Welt würden Sie eine Datei benennen auf einem anderen Laufwerk, wenn Sie diese vollständigen Pfadinformationen nicht zuerst in der Befehlszeile angeben würden?

Jedoch können %~p0, %~n0, %~nx0 Und %~x0 Nützlich sein, wenn Sie sich für Pfad (ohne Laufwerksbuchstaben), Dateiname (ohne Erweiterung) interessieren. , vollständiger Dateiname mit Erweiterung oder nur Dateinamenerweiterung. Beachten Sie jedoch, dass während %~p1 Und %~n1 Den Pfad oder den Namen des ersten Arguments ermitteln, %~nx1 Und %~x1 Das nicht hinzufügen + anzeigen Erweiterung, es sei denn, Sie haben sie bereits in der Befehlszeile verwendet.

15
Kurt Pfeifle

Sie können dafür auch Batch-Funktionen verwenden:

@echo off
setlocal 

goto MAIN
::-----------------------------------------------
:: "%~f2" get abs path of %~2. 
::"%~fs2" get abs path with short names of %~2.
:setAbsPath
  setlocal
  set __absPath=%~f2
  endlocal && set %1=%__absPath%
  goto :eof
::-----------------------------------------------

:MAIN
call :setAbsPath ABS_PATH ..\
echo %ABS_PATH%

endlocal
9
Axel Heider

Kleine Verbesserung zu BrainSlugs83's exzellente Lösung . Verallgemeinert, damit die Ausgabe-Umgebungsvariable im Aufruf benannt werden kann.

@echo off
setlocal EnableDelayedExpansion

rem Example input value.
set RelativePath=doc\build

rem Resolve path.
call :ResolvePath AbsolutePath %RelativePath%

rem Output result.
echo %AbsolutePath%

rem End.
exit /b

rem === Functions ===

rem Resolve path to absolute.
rem Param 1: Name of output variable.
rem Param 2: Path to resolve.
rem Return: Resolved absolute path.
:ResolvePath
    set %1=%~dpfn2
    exit /b

Wenn ausgeführt von C:\project Ausgabe ist:

C:\project\doc\build
8
Lycan

Ich habe nicht viele Lösungen für dieses Problem gesehen. Einige Lösungen verwenden das Durchsuchen von Verzeichnissen mithilfe von CDs, andere verwenden Stapelverarbeitungsfunktionen. Meine persönliche Vorliebe galt für Batch-Funktionen und insbesondere für die Funktion MakeAbsolute , die von DosTips bereitgestellt wird.

Die Funktion hat einige echte Vorteile, in erster Linie, dass sie Ihr aktuelles Arbeitsverzeichnis nicht ändert und zweitens, dass die auszuwertenden Pfade nicht einmal existieren müssen. Hier finden Sie einige hilfreiche Tipps zur Verwendung der Funktion hier .

Hier ist ein Beispielskript und seine Ausgaben:

@echo off

set scriptpath=%~dp0
set siblingfile=sibling.bat
set siblingfolder=sibling\
set fnwsfolder=folder name with spaces\
set descendantfolder=sibling\descendant\
set ancestorfolder=..\..\
set cousinfolder=..\uncle\cousin

call:MakeAbsolute siblingfile      "%scriptpath%"
call:MakeAbsolute siblingfolder    "%scriptpath%"
call:MakeAbsolute fnwsfolder       "%scriptpath%"
call:MakeAbsolute descendantfolder "%scriptpath%"
call:MakeAbsolute ancestorfolder   "%scriptpath%"
call:MakeAbsolute cousinfolder     "%scriptpath%"

echo scriptpath:       %scriptpath%
echo siblingfile:      %siblingfile%
echo siblingfolder:    %siblingfolder%
echo fnwsfolder:       %fnwsfolder%
echo descendantfolder: %descendantfolder%
echo ancestorfolder:   %ancestorfolder%
echo cousinfolder:     %cousinfolder%
GOTO:EOF

::----------------------------------------------------------------------------------
:: Function declarations
:: Handy to read http://www.dostips.com/DtTutoFunctions.php for how dos functions
:: work.
::----------------------------------------------------------------------------------
:MakeAbsolute file base -- makes a file name absolute considering a base path
::                      -- file [in,out] - variable with file name to be converted, or file name itself for result in stdout
::                      -- base [in,opt] - base path, leave blank for current directory
:$created 20060101 :$changed 20080219 :$categories Path
:$source http://www.dostips.com
SETLOCAL ENABLEDELAYEDEXPANSION
set "src=%~1"
if defined %1 set "src=!%~1!"
set "bas=%~2"
if not defined bas set "bas=%cd%"
for /f "tokens=*" %%a in ("%bas%.\%src%") do set "src=%%~fa"
( ENDLOCAL & REM RETURN VALUES
    IF defined %1 (SET %~1=%src%) ELSE ECHO.%src%
)
EXIT /b

Und die Ausgabe:

C:\Users\dayneo\Documents>myscript
scriptpath:       C:\Users\dayneo\Documents\
siblingfile:      C:\Users\dayneo\Documents\sibling.bat
siblingfolder:    C:\Users\dayneo\Documents\sibling\
fnwsfolder:       C:\Users\dayneo\Documents\folder name with spaces\
descendantfolder: C:\Users\dayneo\Documents\sibling\descendant\
ancestorfolder:   C:\Users\
cousinfolder:     C:\Users\dayneo\uncle\cousin

Ich hoffe das hilft ... Es hat mir sicher geholfen :) P.S. Nochmals vielen Dank an DosTips! Du rockst!

4
dayneo

Sie können sie einfach verketten.

SET ABS_PATH=%~dp0 
SET REL_PATH=..\SomeFile.txt
SET COMBINED_PATH=%ABS_PATH%%REL_PATH%

es sieht seltsam aus, wenn sich\..\in der Mitte Ihres Pfades befindet, aber es funktioniert. Keine Notwendigkeit, etwas Verrücktes zu tun :)

1
Kristen

In Ihrem Beispiel würde DIR/B/S ..\somefile.txt aus Bar\test.bat den vollständigen Pfad zurückgeben.

1
George Sisco

die Lösung von stijn funktioniert mit Unterordnern unter C:\Program Files (86)\,

@echo off
set projectDirMc=test.txt

for /f "delims=" %%a in ('powershell -Command "[System.IO.Path]::GetFullPath( '%projectDirMc%' )"') do @set resolvedPath=%%a

echo full path:    %resolvedPath%
0
Irq Mishell
SET CD=%~DP0

SET REL_PATH=%CD%..\..\build\

call :ABSOLUTE_PATH    ABS_PATH   %REL_PATH%

ECHO %REL_PATH%

ECHO %ABS_PATH%

pause

exit /b

:ABSOLUTE_PATH

SET %1=%~f2

exit /b
0
Sergei Sachkov

Dateien Alle anderen Antworten anzeigen

Verzeichnisse

Mit .. Ihr relativer Pfad sein und davon ausgehen, dass Sie derzeit in D:\Projects\EditorProject:

cd .. & cd & cd EditorProject (der relative Pfad)

gibt den absoluten Pfad zurück, z.

D:\Projects

0
Engineer

PowerShell ist heutzutage ziemlich verbreitet, daher verwende ich es oft, um C # schnell aufzurufen, da es Funktionen für so ziemlich alles hat:

@echo off
set pathToResolve=%~dp0\..\SomeFile.txt
for /f "delims=" %%a in ('powershell -Command "[System.IO.Path]::GetFullPath( '%projectDirMc%' )"') do @set resolvedPath=%%a

echo Resolved path: %resolvedPath%

Es ist ein bisschen langsam, aber die gewonnene Funktionalität ist schwer zu übertreffen, es sei denn, Sie greifen auf eine tatsächliche Skriptsprache zurück.

0
stijn