Résoudre chemin absolu de chemin relatif et/ou nom de fichier

y a-t-il un moyen dans un script Windows batch de retourner un chemin absolu à partir d'une valeur contenant un nom de fichier et/ou un chemin relatif?

donnée:

".."
"..somefile.txt"

j'ai besoin du chemin absolu par rapport au fichier batch.

exemple:

  • "unfichier.txt " est situé dans "C:Foo "
  • " test.chauve-souris" est situé dans "C:FooBar".
  • L'utilisateur ouvre une fenêtre de commande dans "C:Foo" et appelle Bartest.bat ..somefile.txt
  • dans le fichier batch "C:Foosomefile.txt" serait dérivé de %1
131
demandé sur Peter Mortensen 2009-10-29 21:58:56

14 réponses

dans les fichiers batch, comme dans les programmes C standard, l'argument 0 contient le chemin du script en cours d'exécution. Vous pouvez utiliser %~dp0 pour obtenir seulement la partie chemin du 0ème argument (qui est le script courant) - ce chemin est toujours un chemin entièrement qualifié.

vous pouvez également obtenir le chemin entièrement qualifié de votre premier argument en utilisant %~f1 , mais cela donne un chemin selon le répertoire de travail courant, qui n'est évidemment pas ce que vous voulez.

personnellement, j'utilise souvent l'idiome %~dp0%~1 dans mon fichier batch, qui interprète le premier argument relatif au chemin du lot d'exécution. Il a un défaut: il échoue lamentablement si le premier argument est complet.

si vous avez besoin de supporter à la fois les chemins absolus relatifs et , vous pouvez faire usage de solution de Frédéric Ménez : changer temporairement le fonctionnement actuel répertoire.

voici un exemple qui démontrera chacune de ces techniques:

@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

si vous sauvegardez ceci comme c:\temp\example.chauve-souris et de les exécuter à partir de c:\Users\Public

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

...vous observerez la sortie suivante:

%~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"
142
répondu Adrien Plisson 2017-05-23 11:47:07

j'ai rencontré un besoin similaire ce matin: comment convertir un chemin relatif en un chemin absolu à l'intérieur d'un script de commande Windows.

a fait le tour:

@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%
136
répondu Frédéric Ménez 2014-11-22 07:49:07

la plupart de ces réponses semblent folles au-dessus du buggy compliqué et super, voici le mien -- il fonctionne sur n'importe quelle variable d'environnement, Pas de %CD% ou PUSHD / POPD , ou for /f non-sens -- juste de vieilles fonctions de fournée simples. -- Le répertoire et le fichier n'ont même pas besoin d'exister.

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

ECHO "%BLAH%"

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

:NORMALIZEPATH
  SET RETVAL=%~dpfn1
  EXIT /B
53
répondu BrainSlugs83 2015-10-29 02:18:51

sans avoir à avoir un autre fichier batch pour passer des arguments à (et utiliser les opérateurs d'argument), vous pouvez utiliser FOR /F :

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

i dans %%~fi est la variable définie à /F %%i . par exemple. si vous avez changé cela en /F %%a alors la dernière partie serait %%~fa .

pour faire la même chose directement à l'invite de commande (et non dans un fichier de lot) remplacer %% par % ...

34
répondu Peter Ritchie 2014-03-25 13:59:07

ceci est pour aider à combler les lacunes dans la réponse D'Adrien Plisson (qui devrait être révoquée dès qu'il l'édite; -):

vous pouvez également obtenir le chemin entièrement qualifié de votre premier argument en utilisant %~f1, mais cela donne un chemin selon le chemin courant, qui n'est évidemment pas ce que vous voulez.

malheureusement, je ne sais pas comment mélanger les deux...

on peut manipuler %0 et %1 de même:

  • %~dpnx0 pour entraînement entièrement qualifié+chemin+Nom+extension du fichier batch lui-même,

    %~f0
  • %~dpnx1 pour lecteur pleinement qualifié+chemin+Nom+extension de son premier argument [si c'est un nom de fichier],

    %~f1

%~f1 "fonctionnera indépendamment de la façon dont vous avez spécifié votre premier argument: avec des chemins relatifs ou avec des chemins absolus (si vous ne spécifiez pas l'extension du fichier lors de la dénomination %1 , il ne sera pas ajouté, même si vous utilisez %~dpnx1 -- cependant.

mais comment diable nommeriez-vous un fichier sur un lecteur différent de toute façon si vous ne donneriez pas ces informations complètes de chemin sur la ligne de commande en premier lieu?

cependant, %~p0 , %~n0 , %~nx0 et %~x0 peut s'avérer pratique, si vous êtes intéressé par le chemin (sans driveletter), le nom du fichier (sans extension), le nom complet du fichier avec extension ou l'extension du nom du fichier seulement. Mais notez, alors que %~p1 et %~n1 fonctionneront pour trouver le chemin ou le nom du premier argument, %~nx1 et %~x1 n'ajouteront pas+afficher l'extension, à moins que vous ne l'ayez déjà utilisé sur la ligne de commande.

15
répondu Kurt Pfeifle 2010-08-13 20:33:11

vous pouvez également utiliser des fonctions par lots pour cela:

@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
8
répondu Axel Heider 2011-07-06 10:51:38

je n'ai pas vu beaucoup de solutions à ce problème. Certaines solutions utilisent le répertoire transversal en utilisant le CD et d'autres utilisent les fonctions batch. Ma préférence personnelle a été pour les fonctions de fournée et en particulier, le MakeAbsolute fonction telle que fournie par DosTips.

la fonction a quelques avantages réels, principalement qu'elle ne change pas votre répertoire de travail actuel et deuxièmement que les chemins évalués n'ont même pas à exister. Vous pouvez trouver quelques conseils utiles sur la façon d'utiliser la fonction ici .

voici un exemple de script et de ses sorties:

@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

et la sortie:

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

j'espère que cela aidera... Il m'a aidé :) P. S. Merci encore à DosTips! Vous rock!

4
répondu dayneo 2012-02-03 13:53:14

Petite amélioration à BrainSlugs83 est une excellente solution . Généralisé pour permettre de nommer la variable d'environnement de sortie dans l'appel.

@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

si l'exécution de C:\project sortie est:

C:\project\doc\build
3
répondu Lycan 2017-10-07 11:32:40

dans votre exemple, de Bar\test.bat, DIR / B / s..\somefile.txt retournerait le chemin complet.

1
répondu George Sisco 2009-10-29 19:17:09

vous pouvez les concaténer.

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

il semble étrange avec \..\ dans le milieu de votre chemin, mais il fonctionne. Pas besoin de faire quelque chose de fou :)

1
répondu Kristen 2012-11-28 00:28:15

PowerShell est assez commun ces jours-ci donc je l'utilise souvent comme un moyen rapide d'invoquer C# Depuis qui a des fonctions pour à peu près tout:

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

c'est un peu lent, mais la fonctionnalité gagnée est difficile à battre à moins que sans recourir à un langage de script réel.

0
répondu stijn 2013-07-07 10:35:15

stijn de la solution fonctionne avec des sous-dossiers de 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
répondu Irq Mishell 2014-11-22 07:47:45

Files voir toutes les autres réponses

annuaires

avec .. étant votre chemin relatif, et en supposant que vous êtes actuellement dans D:\Projects\EditorProject :

cd .. & cd & cd EditorProject (le chemin relatif)

renvoie le chemin absolu par exemple

D:\Projects

0
répondu Arcane Engineer 2015-08-03 08:49:20
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
répondu Sergei Sachkov 2015-09-24 15:43:14