如何使用.bat文件从PATH环境变量中删除特定标记?

时间:2016-07-29 10:19:58

标签: batch-file command-line cmd

我正在编写一个卸载脚本,所以我想“撤消”对系统安装的修改。为实现此目标,我想解析PATH变量,并删除安装添加到PATH的所有值。

为此,我开发了以下伪代码 -

  • PATH的内容保存到临时变量
  • PATH拆分为令牌,使用;字符作为分隔符,并遍历每个令牌
  • (In Loop)确定当前令牌是否是安装添加的令牌
  • (In Loop)如果安装未添加当前令牌,请将其保存以添加到更新的PATH(在临时变量中)
  • 保存更新后的PATH

我希望这个实现相对简单。

第一步,存储PATH很简单。

SET TEMP_PATH=%PATH% 

但是,当我尝试遍历每个令牌时,它将无法正常工作。

FOR /F "delims=;" %%A IN (%TEMP_PATH%) DO ECHO %%A 

此命令仅输出第一个标记,并且不会回显任何后续标记。

所以,我有两个问题 -

  • 如何循环使用未知数量的令牌并与每个令牌一起使用?
  • 还有另一种方法可以实现同样的目标吗?

谢谢。

2 个答案:

答案 0 :(得分:3)

下面的批处理代码会删除脚本顶部定义的一个或多个文件夹路径PathToRemove1PathToRemove2,...来自

  • 用户 PATH 当前用户帐户存储在Windows注册表中的键下 HKEY_CURRENT_USER\Environment
  • 系统 PATH 存储在Windows注册表中的键下 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment

系统 PATH 的更新需要管理员权限,这意味着如果未对执行批处理文件的用户帐户禁用用户帐户控制(UAC),则必须以管理员身份执行批处理文件。

批处理代码仅适用于Windows Vista及更高版本的Windows,因为 SETX 命令默认情况下在Windows XP甚至以前的Windows版本上不可用。

有关命令的可用性 SETX ,请参阅有关SetX和Microsoft的SetX文档的SS64文章。

对于Windows XP与以后Windows版本的reg.exe输出差异,请参阅Rob van der Woude的Reading NT's Registry with REG Query。下面的批处理代码会考虑reg.exe的不同输出。

有关为什么不在执行批处理文件时使用当前定义的本地PATH的解释,请阅读

的问题,答案和注释

从用户和系统中删除文件夹路径的注释批处理代码路径

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "PathToRemove1=C:\Temp\Test"
set "PathToRemove2=C:\Temp"

rem Get directly from Windows registry the system PATH variable value.
for /F "skip=2 tokens=1,2*" %%N in ('%SystemRoot%\System32\reg.exe query "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" /v "Path" 2^>nul') do (
    if /I "%%N" == "Path" (
        set "SystemPath=%%P"
        if defined SystemPath goto CheckSystemPath
    )
)
echo Error: System environment variable PATH not found with a value in Windows registry.
echo/
goto UserPath

:CheckSystemPath
setlocal EnableDelayedExpansion
rem Does the system PATH not end with a semicolon, append one temporarily.
if not "!SystemPath:~-1!" == ";" set "SystemPath=!SystemPath!;"

rem Check case-insensitive for the folder paths to remove as defined at top
rem of this batch script and remove them if indeed found in system PATH.
set "PathModified=0"
for /F "tokens=1* delims==" %%I in ('set PathToRemove') do (
    if not "!SystemPath:%%J;=!" == "!SystemPath!" (
        set "SystemPath=!SystemPath:%%J;=!"
        set "PathModified=1"
    )
)

rem Replace all two or more ; in series by just one ; in system path.
:CleanSystem
if not "!SystemPath:;;=;!" == "!SystemPath!" set "SystemPath=!SystemPath:;;=;!" & goto CleanSystem

rem Remove the semicolon at end of system PATH if there is one.
if "!SystemPath:~-1!" == ";" set "SystemPath=!SystemPath:~0,-1!"

rem Update system PATH using command SETX which requires administrator
rem privileges if the system PATH needs to be modified at all. SETX is
rem by default not installed on Windows XP and truncates string values
rem longer than 1024 characters to 1024 characters. So use alternatively
rem command REG to add system PATH if command SETX cannot be used or is
rem not available at all.
if "%PathModified%" == "1" (
    set "UseSetx=1"
    if not "!SystemPath:~1024,1!" == "" set "UseSetx="
    if not exist %SystemRoot%\System32\setx.exe set "UseSetx="
    if defined UseSetx (
        %SystemRoot%\System32\setx.exe Path "!SystemPath!" /M >nul
    ) else (
        set "ValueType=REG_EXPAND_SZ"
        if "!SystemPath:%%=!" == "!SystemPath!" set "ValueType=REG_SZ"
        %SystemRoot%\System32\reg.exe ADD "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" /f /v Path /t !ValueType! /d "!SystemPath!" >nul
    )
)
endlocal

:UserPath
rem Get directly from Windows registry the user PATH variable value.
for /F "skip=2 tokens=1,2*" %%N in ('%SystemRoot%\System32\reg.exe query "HKCU\Environment" /v "Path" 2^>nul') do (
    if /I "%%N" == "Path" (
        set "UserPath=%%P"
        if defined UserPath goto CheckUserPath
        rem User PATH exists, but with no value, delete user PATH.
        goto DeleteUserPath
    )
)
rem This PATH variable does often not exist and therefore nothing to do here.
goto PathUpdateDone

:CheckUserPath
setlocal EnableDelayedExpansion
rem Does the user PATH not end with a semicolon, append one temporarily.
if not "!UserPath:~-1!" == ";" set "UserPath=!UserPath!;"

rem Check case-insensitive for the folder paths to remove as defined at top
rem of this batch script and remove them if indeed found in user PATH.
set "PathModified=0"
for /F "tokens=1* delims==" %%I in ('set PathToRemove') do (
    if not "!UserPath:%%J;=!" == "!UserPath!" (
        set "UserPath=!UserPath:%%J;=!"
        set "PathModified=1"
        if not defined UserPath goto DeleteUserPath
    )
)

rem Replace all two or more ; in series by just one ; in user path.
:CleanUser
if not "!UserPath:;;=;!" == "!UserPath!" set "UserPath=!UserPath:;;=;!" & goto CleanUser

rem Remove the semicolon at end of user PATH if there is one.
if "!UserPath:~-1!" == ";" set "UserPath=!UserPath:~0,-1!"
if not defined UserPath goto DeleteUserPath

rem Update user PATH using command SETX which does not require administrator
rem privileges if the user PATH needs to be modified at all. SETX is
rem by default not installed on Windows XP and truncates string values
rem longer than 1024 characters to 1024 characters. So use alternatively
rem command REG to add user PATH if command SETX cannot be used or is
rem not available at all.
if "%PathModified%" == "1" (
    set "UseSetx=1"
    if not "!UserPath:~1024,1!" == "" set "UseSetx="
    if not exist %SystemRoot%\System32\setx.exe set "UseSetx="
    if defined UseSetx (
        %SystemRoot%\System32\setx.exe Path "!UserPath!" /M >nul
    ) else (
        set "ValueType=REG_EXPAND_SZ"
        if "!UserPath:%%=!" == "!UserPath!" set "ValueType=REG_SZ"
        %SystemRoot%\System32\reg.exe ADD "HKCU\Environment" /f /v Path /t !ValueType! /d "!UserPath!" >nul
    )
)
goto PathUpdateDone

:DeleteUserPath
rem Delete the user PATH as it contains only folder paths to remove.
%SystemRoot%\System32\reg.exe delete "HKCU\Environment" /v "Path" /f >nul

:PathUpdateDone
rem Other code could be inserted here.
endlocal
endlocal

上面的批处理代码使用简单的不区分大小写的字符串替换和区分大小写的字符串比较来检查当前要删除的路径是否存在于用户或系统 PATH 中。这只有在众所周知如何添加文件夹路径并且用户在此期间未对其进行修改时才有效。有关检查 PATH 是否包含文件夹路径的更安全方法,请参阅How to check if directory exists in %PATH%?撰写的dbenham上的答案。

注意:此批处理代码并非旨在处理系统用户 PATH包含的非常罕见的用例包含在双引号中的路径字符串中带有一个或多个分号的文件夹路径,以便将双引号文件夹路径字符串中的Windows解释为;作为文字字符而不是文件夹路径之间的分隔符。

要了解使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并完全阅读为每个命令显示的所有帮助页面。

  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • if /?
  • reg /?
  • reg add /?
  • reg delete /?
  • reg query /?
  • rem /?
  • set /?
  • setlocal /?
  • setx /?

另请参阅Microsoft关于>nul的文章,了解2>nul>的说明,其中重定向运算符^使用reg.exe进行转义,以便在执行时使用重定向2>nul而不是解释MSSQL2014 - AdventureWorks2014 database错误放置命令 FOR ,这会导致Windows命令解释程序因语法错误而退出批处理。

答案 1 :(得分:1)

此命令仅输出第一个标记,并且不会回显后续标记。

FOR /F "delims=;" %%A IN (%TEMP_PATH%) DO ECHO %%A 
  

如何循环使用未知数量的令牌并与每个令牌一起使用?

使用以下批处理文件。

<强> SplitPath.cmd

@echo off
setlocal
for %%a in ("%path:;=";"%") do (
  echo %%~a
  )
endlocal

示例输出

F:\test>path
PATH=C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\apps\WSCC\Sysinternals Suite;C:\apps\WSCC\NirSoft Utilities

F:\test>splitpath
C:\Windows\system32
C:\Windows
C:\Windows\System32\Wbem
C:\Windows\System32\WindowsPowerShell\v1.0\
C:\apps\WSCC\Sysinternals Suite
C:\apps\WSCC\NirSoft Utilities

注意:

  • 根据需要修改for循环以实现其余的伪代码。

进一步阅读