batch-file - 如何仅获取用户路径变量?

标签 batch-file

Echo %PATH%返回 系统路径变量 + 用户 路径变量。

如何获得只有用户 路径变量?

最佳答案

系统 PATH 变量存储在 Windows 注册表中,其值 Path 类型为 REG_EXPAND_SZ,其中包含对环境变量(如 %SystemRoot%)的引用,或者如果不正确,则由 REG_SZ 类型的应用程序修改而没有 key 下的环境变量引用

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment

用户 PATH 变量默认不存在于 Windows 注册表中,但一旦由应用程序创建或由用户手动创建,其值 Path 的类型 REG_EXPAND_SZREG_SZ 会存储在 Windows 注册表中
HKEY_CURRENT_USER\Environment

外部指令 REG 与命令QUERY可用于系统的值或用户 PATH直接从使用标准用户权限的Windows注册表变量。

只需一个命令行就可以从 Windows 注册表中读取 用户 PATH 变量,并将其值分配给环境变量 UserPath,另外扩展目录路径列表中的所有环境变量。
@echo off

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" call set "UserPath=%%P" & goto UserPathRead

echo There is no user PATH defined.
echo/
pause
goto :EOF

:UserPathRead
echo The user PATH is: %UserPath%
echo/
set "UserPath="
pause
reg query 的输出格式取决于 Windows 版本,这使得附加的不区分大小写的 IF 条件成为必要。有关 reg query 输出格式的详细信息,请参见 Rob van der Woude 编写的 Reading NT's Registry with REG Query 示例。
reg query HKCU\Environment /v Path 在 Windows XP 上的示例输出:
 
! REG.EXE VERSION 3.0

HKEY_CURRENT_USER\Environment
    Path        REG_SZ  C:\BatUtils
 

输出的开头有一个空行,输出的结尾还有一个空行,还有一个标题行和一个在带有注册表项的行上方的另一个空行。

包含感兴趣数据的行以 4 个空格字符开头,接下来是不区分大小写的环境变量 Path 的名称。然后将单个水平制表符输出到注册表值类型 REG_SZ 。最后在输出 Path 的字符串值之前还有一个水平制表符,它也可以包含 1 个或多个空格字符。
reg query HKCU\Environment /v Path 在 Windows 7 上的示例输出:
 
HKEY_CURRENT_USER\Environment
    Path    REG_SZ    C:\BatUtils
 

输出的开头还有一个空行,输出的结尾还有一个空行。但是没有标题。第二行已包含注册表项。

包含感兴趣数据的行以 4 个空格字符开头,接下来是不区分大小写的环境变量 Path 的名称。然后将 4 个空格而不是制表符输出到注册表值类型 REG_SZ 。最后,在输出 Path 的字符串值之前还有 4 个空格而不是制表符,它也可以包含 1 个或多个空格字符。

命令 REG 在后台的单独命令进程中由 FOR 执行。 REG 输出的错误消息用于处理 STDERR 在注册表项 HKCU\Environment 或值 Path 不存在的情况下,通过将其重定向到设备 N10456707070707010456070707 来抑制注册表项 2>nul 或值 > 不存在重定向操作符 ^ 必须在此处使用插入字符 "skip=2 tokens=1,2*" 进行转义,以便在 Windows 命令解释器解析 FOR 命令行时被解释为文字字符,但在稍后执行 REG 40207 REG 407 后台命令行 REG 407 独立后台命令行时作为重定向操作符

使用 N 定义的 FOR 选项导致跳过 REG 输出的前两行,并使用默认的制表符将其他行拆分为 3 个子字符串(分隔符)。

第一个空格/制表符分隔的字符串分配给第一个循环变量 O,它是到达感兴趣数据行时的变量名称。

作为注册表值类型的第二个子字符串被分配给循环变量 P 作为 ASCII table 中的下一个字符。这种行为是 FOR 循环变量区分大小写的原因。

由于 * 之后的选项字符串中的 tokens=1,2 ,第二个子字符串之后的空格/制表符之后的所有内容都被分配给循环变量 Path 而不会拆分行的其余部分。

因此,在 Windows Vista 和更高版本的 Windows 上,命令 FOR 作为 REG 带有 PATH 的行的输出的第一行进行处理,而在 Windows XP 上,处理的第一行是注册表项的第一行,其原因是 REG
条件是必要的。

命令 GOTO 用于退出上具有成功地读取从Windows注册表中的用户 PATH变量和现有用户 PATH被读取之后,跳转到命令块用于进一步处理 FOR 回路。但是,如果 用户 PATH 变量在 Windows 注册表中根本不存在,则会到达 FOR 循环下方的命令块。

为了完整起见,批处理代码
  • 从 Windows 注册表读取 系统 用户 PATH
  • 将两个 PATH 变量连接到 PATH 并覆盖 本地 PATH 在当前环境中的当前命令进程中,
  • 扩展;; 值中的环境变量,
  • 将所有 ; 替换为 PATH 值中的 ;
  • 如果有 PATH 值,则从 PATH 值的末尾删除 PATH

  • 如果 用户 PATH 包含 1 个或多个目录路径,则此批处理代码不会像 Windows 那样检查 系统 call /? 中已经存在的目录路径,然后再将它们连接起来。所以有可能一个目录路径在 本地 echo /? 最终出现不止一次。
    @echo off
    rem Get directly from Windows registry the system PATH variable value.
    set "SystemPath="
    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"
            goto GetUserPath
        )
    )
    
    rem Get directly from Windows registry the user PATH variable value.
    :GetUserPath
    set "UserPath="
    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"
            goto SetPath
        )
    )
    
    rem Concatenate the two PATH values to a single value and expand variables.
    rem Delete the two environment variables not further needed.
    rem Next replace all two consecutive semicolons by a single semicolon.
    rem Last remove semicolon from end of directory list if there is one.
    
    :SetPath
    call set "PATH=%SystemPath%;%UserPath%"
    set "SystemPath="
    set "UserPath="
    set "PATH=%PATH:;;=;%"
    if "%PATH:~-1%" == ";" set "PATH=%PATH:~0,-1%"
    

    要了解使用的命令及其工作原理,请打开命令提示符窗口,在那里执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。
  • for /?
  • goto /?
  • if /?
  • pause /?
  • reg /?
  • reg query /?
  • rem /?
  • set /?
  • 2>nul
  • &

  • 另请阅读有关 Using Command Redirection Operators 的 Microsoft 文章以了解 ojit_code 的说明,以及有关堆栈溢出主题 Single line with multiple commands using Windows batch file 的答案,了解命令行上运算符 ojit_code 的含义。

    关于batch-file - 如何仅获取用户路径变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43934167/

    相关文章:

    mysql - 从 bat 文件中禁用 Mysql 外键约束 (FOREIGN_KEY_CHECKS)

    batch-file - xcopy 到受密码保护的网络位置

    windows - 当存在名为 nul 的文件时,nul 如何工作

    windows - 删除小于特定大小的文件

    linux - 从 Windows 执行远程 .sh 文件

    batch-file - 如何在纯批处理脚本中生成不重复的随机数列表?

    batch-file - 如何解压文件夹所有子文件夹中的所有 rar 文件,然后删除文件?

    windows - 批处理文件: List Directory & File names to individual variables and display as selection menu

    windows - 为什么以参数/等待开始的命令无法正常工作?

    windows - .bat 中的 "echo"非常慢