183 votes

Résoudre le chemin absolu à partir du chemin relatif et/ou du nom de fichier

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

Donné :

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

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

Exemple :

  • "somefile.txt" est situé dans "C:\Foo\"
  • "test.bat" est situé dans "C:\Foo\Bar".
  • L'utilisateur ouvre une fenêtre de commande dans "C:\Foo" et appelle Bar\test.bat ..\somefile.txt
  • Dans le fichier batch, "C:\Foo\somefile.txt" serait dérivé de %1

1 votes

Les chemins relatifs ne sont pas la fin de l'histoire. Considérez également les liens symboliques NTFS : il est fort probable que vous ayez également besoin d'un analogue de realpath pour une normalisation fiable des chemins.

0 votes

Probablement, vous n'avez pas besoin d'un chemin exact du tout ! Vous pouvez simplement ajouter un chemin de base: SET FilePath=%CD%\%1 afin que cela ressemble à C:\Foo\Bar\..\..\some\other\dir\file.txt. Les programmes semblent comprendre un tel chemin compliqué.

0 votes

Beaucoup de ces réponses sont trop compliquées ou tout simplement boguées - mais, c'est en fait quelque chose de assez facile à faire en lot, jetez un coup d'œil à ma réponse ci-dessous.

180voto

Adrien Plisson Points 9750

Dans les fichiers batch, tout 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 uniquement la partie du chemin de l'argument 0 (qui est le script actuel) - 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 actuel, ce 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 par rapport au chemin du batch en cours d'exécution. Cela a cependant un inconvénient : il échoue misérablement si le premier argument est entièrement qualifié.

Si vous devez prendre en charge à la fois les chemins relatifs et absolus, vous pouvez utiliser la solution de Frédéric Ménez : changer temporairement le répertoire de travail actuel.

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 Changer temporairement le répertoire de travail actuel, pour récupérer un chemin complet vers le premier paramètre
pushd .
cd %~dp0
echo batch-relative %%~f1 is "%~f1"
popd

Si vous enregistrez ceci en tant que c:\temp\example.bat et l'exécutez depuis c:\Users\Public comme

c:\Users\Public>\temp\example.bat ..\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"

La documentation pour l'ensemble des modificateurs autorisés sur un argument de batch peut être trouvée ici : https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/call

5 votes

Vous pouvez manipuler %0 et %1 de la même manière: %~dpnx0 pour le chemin et le nom complet du fichier batch lui-même, %~dpnx1 pour le chemin et le nom complet de son premier argument [si c'est un fichier]. (Mais comment diable nommeriez-vous un fichier sur un lecteur différent si vous ne donneriez pas ces informations de chemin complet sur la ligne de commande de toute façon?)

0 votes

Cet exemple est bien plus complexe que la réponse de @frédéric-ménez

3 votes

Cela échoue sur les liens symboliques NTFS.

167voto

Frédéric Ménez Points 766

Je suis tombé sur un besoin similaire ce matin : comment convertir un chemin relatif en un chemin absolu à l'intérieur d'un script de commande Windows.

La solution suivante a fonctionné :

@echo off

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

rem // Sauvegarder le répertoire actuel et changer vers le répertoire cible
pushd %REL_PATH%

rem // Sauvegarder la valeur de la variable CD (répertoire actuel)
set ABS_PATH=%CD%

rem // Restaurer le répertoire original
popd

echo Chemin relatif : %REL_PATH%
echo Correspond au chemin : %ABS_PATH%

3 votes

Ceci est VRAIMENT utile. Y a-t-il des bonnes ressources pour des astuces de fichiers batch comme celui-ci?

8 votes

Ne pensez pas qu'il est nécessaire d'avoir le "pushd" suivi de "cd". Vous pouvez simplement faire "pushd %REL_PATH%". Cela enregistrera le répertoire actuel et passera à REL_PATH en une seule fois.

1 votes

@DannyParker Une collection utile de techniques Batch et exemples de scripts se trouve sur robvanderwoude.com/batchfiles.php. Voir également stackoverflow.com/questions/245395/…

38voto

Peter Ritchie Points 18352

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

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

Pour faire la même chose directement dans l'invite de commandes (et pas dans un fichier batch), remplacez %% par %...

0 votes

Ne pas changer de répertoire est important, car cela rend la recette robuste au fait que la commande cd ne change pas nécessairement la variable d'environnement %CD% (si par exemple vous êtes sur le lecteur D: et que votre chemin cible est sur C:)

0 votes

@jez Pour cela, vous pourriez utiliser cd /D D:\sur.autre.disque

2 votes

POUR /F %%i DANS ("..\relativePath") FAIRE echo chemin absolu : %%~fi échouera si le ..\relativePath contient des espaces

15voto

Kurt Pfeifle Points 24491

Ceci est pour aider à combler les lacunes dans la réponse d'Adrien Plisson (qui devrait être upvotée dès qu'il la modifiera ;-):

vous pouvez également obtenir le chemin d'accès complet de votre premier argument en utilisant %~f1, mais cela donne un chemin en fonction du chemin actuel, ce qui n'est évidemment pas ce que vous voulez.

malheureusement, je ne sais pas comment les combiner...

On peut gérer %0 et %1 de la même manière :

  • %~dpnx0 pour le lecteur+chemin d'accès+nom+extension complète du fichier batch lui-même,
    %~f0 suffit également ;
  • %~dpnx1 pour le lecteur+chemin d'accès+nom+extension complète de son premier argument [si c'est un nom de fichier du tout],
    %~f1 suffit également ;

%~f1 fonctionnera indépendamment de la manière dont vous avez spécifié votre premier argument : avec des chemins relatifs ou des chemins absolus (si vous ne spécifiez pas l'extension du fichier lors du nommage de %1, elle ne sera pas ajoutée, 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 fournissez pas ces informations de chemin complet en ligne de commande en premier lieu ?

Cependant, %~p0, %~n0, %~nx0 et %~x0 peuvent être utiles, si vous êtes intéressés par le chemin (sans la lettre du lecteur), le nom du fichier (sans l'extension), le nom complet du fichier avec l'extension ou l'extension du fichier seulement. Mais notez que, tandis que %~p1 et %~n1 fonctionneront pour trouver le chemin ou le nom du premier argument, %~nx1 et %~x1 n'ajouteront pas+l'afficheront pas l'extension, sauf si vous l'avez déjà utilisée en ligne de commande.

0 votes

Le problème avec %~dpnx1 est qu'il donne le chemin d'accès complet de l'argument par rapport au répertoire actuel, alors que l'OP souhaite que le chemin soit relatif au répertoire où se trouve le fichier batch.

1 votes

@Adrien Plisson: %~dpnx1 donne le chemin complet du premier argument. Pas du tout relatif, et non relatif au répertoire actuel non plus. Le d est pour le lecteur, le p est pour le chemin, le n est pour le nom de fichier sans suffixe, le x est pour le suffixe, le 1 est pour le premier argument. -- Et la question de Nathan était : "Y a-t-il un moyen de retourner un chemin absolu à partir d'une valeur contenant un nom de fichier et/ou un chemin relatif?"

0 votes

Les chemins absolus et relatifs utilisation et source avec une description. Reconnaissant!

12voto

Axel Heider Points 61

Vous pouvez également utiliser des fonctions batch pour cela :

@echo off
setlocal 

goto MAIN
::-----------------------------------------------
:: "%~f2" obtenir le chemin absolu de %~2. 
::"%~fs2" obtenir le chemin absolu avec des noms courts de %~2.
:setAbsPath
  setlocal
  set __absPath=%~f2
  endlocal && set %1=%__absPath%
  goto :eof
::-----------------------------------------------

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

endlocal

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X