web-dev-qa-db-fra.com

Comment vérifier si le répertoire existe dans% PATH%?

Comment vérifier si un répertoire est déjà présent dans la variable d'environnement PATH? Voici un début. Tout ce que j'ai réussi à faire avec le code ci-dessous, cependant, est de faire écho le premier répertoire dans% PATH%. Comme il s’agit d’une boucle FOR, on pourrait penser qu’elle énumérerait tous les répertoires de% PATH%, mais elle n’obtient que le premier. 

Existe-t-il une meilleure façon de le faire? Quelque chose comme find ou findstr opérant sur la variable% PATH%? Je voudrais juste vérifier si un répertoire existe dans la liste des répertoires dans% PATH%, afin d'éviter d'ajouter quelque chose qui existe déjà.

FOR /F "delims=;" %%P IN ("%PATH%") DO (
    @ECHO %%~P
)
58
Axl

Je n'ai pas fait de programmation par lots depuis un moment, mais:

echo ;%PATH%; | find /C /I ";<string>;"

devrait vous donner 0 si la chaîne n'est pas trouvée et 1 ou plus si c'est le cas.

EDIT: Ajout du drapeau insensible à la casse, grâce à Panos.

36
Randy

Un autre moyen de vérifier si quelque chose se trouve dans le chemin consiste à exécuter un exécutable innocent qui ne va pas échouer s'il est présent et à vérifier le résultat. À titre d’exemple, l’extrait de code suivant vérifie si maven est dans le chemin:

mvn --help > NUL 2> NUL 
if errorlevel 1 goto mvnNotInPath

Donc, j'essaie de lancer mvn --help, d'ignorer la sortie (je ne veux pas voir l'aide si maven est là) (> NUL) et d'afficher le message d'erreur si maven n'était pas trouvé (2> NUL).

21
bert bruynooghe

Après avoir lu les réponses ici, je pense pouvoir fournir un nouveau point de vue: si le but de cette question est de savoir si le chemin d'accès à un certain fichier exécutable existe dans %PATH% et si ce n'est pas le cas, insérez-le (et c’est la seule raison pour le faire, je pense), alors cela peut être résolu de manière légèrement différente: "Comment vérifier si le répertoire d’un certain programme exécutable existe dans% PATH%"? Cette question peut être facilement résolue de cette façon:

for %%p in (programname.exe) do set "progpath=%%~$PATH:p"
if not defined progpath (
   rem The path to programname.exe don't exist in PATH variable, insert it:
   set "PATH=%PATH%;C:\path\to\progranname"
)

Si vous ne connaissez pas l'extension du fichier exécutable, vérifiez-les tous:

set "progpath="
for %%e in (%PATHEXT%) do (
   if not defined progpath (
      for %%p in (programname.%%e) do set "progpath=%%~$PATH:p"
   )
)
7
Aacini

Si vous utilisez for et delims , vous ne pouvez pas capturer un nombre arbitraire de champs (comme l'a souligné Adam aussi), vous devez donc utiliser une technique de bouclage. Le script de commande suivant répertorie chaque chemin de la variable d’environnement PATH sur une ligne distincte:

@echo off 
setlocal 
if "%~1"=="" (
    set PATHQ=%PATH%
) else (
    set PATHQ=%~1 ) 
:WHILE
    if "%PATHQ%"=="" goto WEND
    for /F "delims=;" %%i in ("%PATHQ%") do echo %%i
    for /F "delims=; tokens=1,*" %%i in ("%PATHQ%") do set PATHQ=%%j
    goto WHILE 
:WEND

Il simule une construction classique whilewend trouvée dans de nombreux langages de programmation . Avec ceci en place, vous pouvez utiliser quelque chose comme findstr pour filtrer et rechercher ensuite un chemin particulier. Par exemple, si vous avez enregistré le script ci-dessus dans un fichier appelé tidypath.cmd, voici comment vous pouvez diriger vers findstr, en recherchant des chemins dans le répertoire des programmes standard (à l'aide d'une correspondance ne respectant pas la casse):

> tidypath | findstr /i "%ProgramFiles%"
6
Atif Aziz

Ceci recherchera une correspondance exacte mais insensible à la casse, alors faites attention aux barres obliques inverses finales, etc.:

for %P in ("%path:;=";"%") do @if /i %P=="PATH_TO_CHECK" echo %P exists in PATH

ou, dans un fichier de commandes (par exemple, checkpath.bat) qui prend un argument:

@for %%P in ("%path:;=";"%") do @if /i %%P=="%~1" echo %%P exists in PATH

Dans cette dernière forme, on pourrait appeler par exemple checkpath "%ProgramFiles%" pour voir si le chemin spécifié existe déjà dans PATH.

Veuillez noter que cette implémentation suppose qu'aucun point-virgule ni aucune citation ne sont présents dans un élément de chemin d'accès unique.

4
mousio

J'ai pris votre implémentation en utilisant la boucle pour et l'ai étendue en quelque chose qui parcourt tous les éléments du chemin. Chaque itération de la boucle for supprime le premier élément du chemin (% p) de tout le chemin (contenu dans% q et% r).

@echo off
SET MYPATHCOPY=%PATH%

:search
for /f "delims=; tokens=1,2*" %%p in ("%MYPATHCOPY%") do (
   @echo %%~p
   SET MYPATHCOPY=%%~q;%%~r
)

if "%MYPATHCOPY%"==";" goto done;
goto search;

:done

Exemple de sortie:

Z:\>path.bat
C:\Program Files\Microsoft DirectX SDK (November 2007)\Utilities\Bin\x86
c:\program files\imagemagick-6.3.4-q16
C:\WINDOWS\system32
C:\WINDOWS
C:\SFU\common\
c:\Program Files\Debugging Tools for Windows
C:\Program Files\Nmap
2
indiv

Si votre question était "pourquoi ce fragment de script cmd ne fonctionne-t-il pas?" alors la réponse est que for /f itère sur des lignes. La delims divise les lignes en champs, mais vous ne capturez que le premier champ dans %%P. Il n'y a aucun moyen de capturer un nombre arbitraire de champs avec une boucle for /f.

2
Adam Mitz

Vous pouvez également utiliser le remplacement de sous-chaîne pour tester la présence d'une sous-chaîne. Ici, je supprime les guillemets pour créer PATH_NQ, puis je retire "c:\mydir" du PATH_NQ et le compare à l'original pour voir si quelque chose a changé:

set PATH_NQ=%PATH:"=%
if not "%PATH_NQ%"=="%PATH_NQ:c:\mydir=%" goto already_in_path
set PATH=%PATH%;c:\mydir
:already_in_path
2
Kevin Edwards

Ajouter un répertoire à PATH s'il n'existe pas déjà:

set myPath=c:\mypath
For /F "Delims=" %%I In ('echo %PATH% ^| find /C /I "%myPath%"') Do set pathExists=%%I 2>Nul
If %pathExists%==0 (set PATH=%myPath%;%PATH%)
2
Noam Manos

J'ai combiné certaines des réponses ci-dessus pour arriver à ceci afin de garantir qu'une entrée de chemin donnée existe exactement comme indiqué avec autant de brièveté que possible et sans écho de bugs sur la ligne de commande.

set myPath=<pathToEnsure | %1>
echo ;%PATH%; | find /C /I ";%myPath%;" >nul
if %ERRORLEVEL% NEQ 0 set PATH=%PATH%;%myPath%
2
Redsplinter

Vous pouvez accomplir cela en utilisant PoweShell;

Test-Path $ENV:SystemRoot\YourDirectory
Test-Path C:\Windows\YourDirectory

Ceci retourne TRUE ou FALSE

Court, simple et facile!

1
Heyvoon

En vous appuyant sur la réponse de rcar, vous devez vous assurer qu'une sous-chaîne de la cible n'est pas trouvée.

if a%X%==a%PATH% echo %X% is in PATH
echo %PATH% | find /c /i ";%X%"
if errorlevel 1 echo %X% is in PATH
echo %PATH% | find /c /i "%X%;"
if errorlevel 1 echo %X% is in PATH
1
Adam Mitz

Juste comme alternative:

  1. Dans le dossier dans lequel vous allez rechercher la variable PATH, créez un fichier temporaire portant un nom si inhabituel que vous ne vous attendriez jamais à recevoir d'un autre fichier sur votre ordinateur.

  2. Utilisez la structure de script batch standard qui vous permet de rechercher un fichier en recherchant une liste de répertoires définie par une variable d’environnement (généralement PATH).

  3. Vérifiez si le résultat de la recherche correspond au chemin en question et affichez le résultat.

  4. Supprimer le fichier temporaire.

Cela pourrait ressembler à ceci:

@ECHO OFF
SET "mypath=D:\the\searched-for\path"
SET unusualname=nowthisissupposedtobesomeveryunusualfilename
ECHO.>"%mypath%\%unusualname%"
FOR %%f IN (%unusualname%) DO SET "foundpath=%%~dp$PATH:f"
ERASE "%mypath%\%unusualname%"
IF "%mypath%" == "%foundpath%" (
  ECHO The dir exists in PATH
) ELSE (
  ECHO The dir DOES NOT exist in PATH
)

Problèmes connus:

  1. La méthode ne peut fonctionner que si le répertoire existe (ce qui n'est pas toujours le cas).

  2. La création/suppression de fichiers dans un répertoire affecte son attribut «date/heure modifiée» (ce qui peut parfois être un effet indésirable).

  3. Créer un nom de fichier unique dans le monde entier dans l’esprit ne peut pas être considéré comme très fiable. Générer un tel nom n’est pas en soi une tâche triviale.

1
Andriy M

Cette version fonctionne assez bien. Il vérifie simplement si vim71 est dans le chemin et le précède sinon.

@echo off
echo %PATH% | find /c /i "vim71" > nul
if not errorlevel 1 goto jump
PATH = C:\Program Files\Vim\vim71\;%PATH%
:jump

Cette démonstration a pour but d’illustrer la logique du niveau d’erreur:

@echo on
echo %PATH% | find /c /i "Windows"
if "%errorlevel%"=="0" echo Found Windows
echo %PATH% | find /c /i "Nonesuch"
if "%errorlevel%"=="0" echo Found Nonesuch

La logique est inversée dans le code vim71 car errorlevel 1 équivaut à errorlevel> = 1. Il s'ensuit que errorlevel 0 sera toujours évalué comme étant vrai, "not errorlevel 1" est utilisé.

Postscript La vérification peut ne pas être nécessaire si vous utilisez setlocal et endlocal pour localiser les paramètres de votre environnement, par exemple.

@echo off
setlocal
PATH = C:\Program Files\Vim\vim71\;%PATH%
rem your code here
endlocal

Après endlocal, vous êtes de retour avec votre chemin d'origine.

1
Chris Degnen

C'est une variante de la réponse de Kevin Edwards utilisant le remplacement de chaîne . Le modèle de base est le suivant:

IF "%PATH:new_path=%" == "%PATH%" PATH=%PATH%;new_path

Par exemple:

IF "%PATH:C:\Scripts=%" == "%PATH%" PATH=%PATH%;C:\Scripts

En un mot, nous faisons un test conditionnel dans lequel nous essayons de supprimer/remplacer new_path de notre variable d'environnement PATH. Si new_path n'existe pas, la condition réussit et le new_path sera ajouté à PATH pour la première fois. Si new_path existe déjà, la condition échoue et nous n’ajouterons pas new_path une seconde fois.

1
Stephen Quan

Un commentaire sur le script "addPath"; Lorsque vous fournissez un chemin avec des espaces, il lève.

Exemple: Call addPath "c:\Fichiers de programme (x86)\SDK Microsoft\Windows\v7.0A\Bin"

rendements: Les «fichiers» ne sont pas reconnus comme une commande interne ou externe, un programme exploitable ou un fichier de commandes

1
Morten Grøtan

Vous indiquez que vous souhaitez éviter d’ajouter le répertoire au chemin de recherche s’il existe déjà. Votre intention est-elle de stocker le répertoire de manière permanente dans le chemin, ou juste temporairement pour un fichier de traitement par lots?

Si vous souhaitez ajouter (ou supprimer) des répertoires de façon permanente à PATH, consultez l'utilitaire Gestionnaire de chemins (pathman.exe) des Outils du Kit de ressources Windows pour les tâches administratives, http://support.Microsoft.com/kb/927229 . Avec cela, vous pouvez ajouter ou supprimer des composants des chemins système et utilisateur, et il gérera les anomalies telles que les entrées en double.

Si vous devez modifier le chemin uniquement temporairement pour un fichier de commandes, je voudrais simplement ajouter le chemin supplémentaire devant le chemin, avec le risque de perte de performance légère en raison d'une entrée dupliquée dans le chemin.

1
ketorin

En général, cela consiste à mettre un exe/dll sur le chemin. Tant que ce fichier n'apparaîtra nulle part ailleurs:

@echo off
where /q <put filename here>    
if %errorlevel% == 1 (
    setx PATH "%PATH%;<additional path stuff>"
) else (
    echo "already set path"
)
1
user1454091

Cette routine recherchera un chemin\ou fichier.ext dans la variable cheminit renvoie 0 s'il est trouvé. Le chemin\ou le fichier peut contenir des espaces s'il est cité . Si une variable est passée comme dernier argument, elle sera définie sur d:\path\file.

@echo off&goto :PathCheck
:PathCheck.CMD
echo.PathCheck.CMD: Checks for existence of a path or file in %%PATH%% variable
echo.Usage: PathCheck.CMD [Checkpath] or [Checkfile] [PathVar]
echo.Checkpath must have a trailing \ but checkfile must not
echo.If Checkpath contains spaces use quotes ie. "C:\Check path\"
echo.Checkfile must not include a path, just the filename.ext
echo.If Checkfile contains spaces use quotes ie. "Check File.ext"
echo.Returns 0 if found, 1 if not or -1 if checkpath does not exist at all
echo.If PathVar is not in command line it will be echoed with surrounding quotes
echo.If PathVar is passed it will be set to d:\path\checkfile with no trailing \
echo.Then %%PathVar%% will be set to the fully qualified path to Checkfile
echo.Note: %%PathVar%% variable set will not be surrounded with quotes
echo.To view the path listing line by line use: PathCheck.CMD /L
exit/b 1

:PathCheck
if "%~1"=="" goto :PathCheck.CMD
setlocal EnableDelayedExpansion
set "PathVar=%~2"
set "pth="
set "pcheck=%~1"
if "%pcheck:~-1%" equ "\" (
  if not exist %pcheck% endlocal&exit/b -1
  set/a pth=1
) 
for %%G in ("%path:;=" "%") do (
  set "Pathfd=%%~G\"
  set "Pathfd=!Pathfd:\\=\!"
  if /i "%pcheck%" equ "/L" echo.!Pathfd!
  if defined pth (
    if /i "%pcheck%" equ "!Pathfd!" endlocal&exit/b 0
  ) else (
    if exist "!Pathfd!%pcheck%" goto :CheckfileFound
  )
)
endlocal&exit/b 1

:CheckfileFound
endlocal&(
  if not "%PathVar%"=="" (
    call set "%~2=%Pathfd%%pcheck%"
  ) else (echo."%Pathfd%%pcheck%")
  exit/b 0
)
0
carlsomo

Juste pour élaborer sur la réponse de Heyvoon (2015.06.08) à l'aide de Powershell, ce script Powershell simple devrait vous donner des détails sur% path%

$env:Path -split ";" | % {"$(test-path $_);$_"}

générer ce type de sortie que vous pouvez vérifier indépendamment

True;C:\WINDOWS
True;C:\WINDOWS\system32
True;C:\WINDOWS\System32\Wbem
False;C:windows\System32\windowsPowerShell\v1.0\
False;C:\Program Files (x86)\Java\jre7\bin

réassembler pour mettre à jour le chemin:

$x=$null;foreach ($t in ($env:Path -split ";") ) {if (test-path $t) {$x+=$t+";"}};$x
0
Albert

-contains a travaillé pour moi

$pathToCheck = "c:\some path\to\a\file.txt"

$env:Path - split ';' -contains $pathToCheck

Pour ajouter le chemin quand il n'existe pas encore j'utilise

$pathToCheck = "c:\some path\to\a\file.txt"

if(!($env:Path -split ';' -contains $vboxPath)) {
  $documentsDir = [Environment]::GetFolderPath("MyDocuments")
  $profileFilePath = Join-Path $documentsDir "WindowsPowerShell/profile.ps1"
  Out-File -FilePath $profileFilePath -Append -Force -Encoding ascii -InputObject "`$env:Path += `";$pathToCheck`""
  Invoke-Expression -command $profileFilePath
}
0
Günter Zöchbauer