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
)
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.
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).
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"
)
)
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 while… wend 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%"
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.
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
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
.
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
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%)
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%
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!
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
Juste comme alternative:
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.
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
).
Vérifiez si le résultat de la recherche correspond au chemin en question et affichez le résultat.
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:
La méthode ne peut fonctionner que si le répertoire existe (ce qui n'est pas toujours le cas).
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).
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.
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.
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.
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
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.
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"
)
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
)
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
-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
}