如何列出所有变量名称以及它们当前的值?

如何列出所有变量名称及其当前值?
包括不仅限于$HOME、$PWD等已定义的任何其他变量。

5http://superuser.com/questions/420295/how-do-i-see-a-list-of-all-currently-defined-environment-variables-in-a-linux-ba - Ciro Santilli OurBigBook.com
8你接受了一个错误的答案。"printenv"只会给出环境变量。如果你真的想要当前在你的shell中声明的所有变量,使用"declare -p"或者"typeset -p"。 - Florin Andrei
11个回答

对于bash:(Ubuntu中的标准shell)

在终端中输入以下命令以打印所有环境变量:

printenv

如需有关此命令的更多信息,请阅读printenv man page
要显示包括“shell变量”在内的列表,您可以输入以下命令:
( set -o posix ; set ) | less

这将向您显示不仅 shell 变量,还有环境变量。

有关此主题的更多信息,请阅读:


对于zsh:(一个高级的shell)

使用以下命令:

( setopt posixbuiltin; set; ) | less

有关ZSH选项的更多信息,请参阅zshoptions man page

20如果我去终端并输入MYNEWVARIABLE=Ubuntu,然后执行printenv,它不会显示出来。为什么会这样,其他的变量又是如何显示出来的呢? - Strapakowsky
@Strapakowsky 我心里想着这个问题,然后找到了一个可能的解决方案。请阅读我的更新答案。 - Lucio
8可能你正在看到一个shell变量和一个环境变量之间的区别。试试export MYNEWVARIABLE=Ubuntu,它会按照你的期望工作。 - Rmano
5如果你只是执行 set,它会列出你创建的变量。或者执行 set | grep myvar - Sergiy Kolodyazhnyy
8printenv 是一个外部命令,因此它只知道(并打印)已导出的环境变量。set 是一个内部的 bash 命令,所以它显示所有的 "shell 变量"(未导出的环境变量)以及已导出的环境变量。 - Dan Pritts
也适用于OSX操作系统 - Craig Wayne
2对于@Rmano对@Strapakowsky的回复进行扩展... 这样做是行不通的 unset MYNEWVARIABLE; MYNEWVARIABLE=Ubuntu; printenv | grep MYNEW,但这样可以 unset MYNEWVARIABLE; export MYNEWVARIABLE=Ubuntu; printenv | grep MYNEW,而这样也可以 unset MYNEWVARIABLE; MYNEWVARIABLE=Ubuntu printenv | grep MYNEW。使用export命令表示“我设置的变量应该成为传递给进程的环境的一部分,而不仅仅是此shell中的一个变量。”我的第三个示例表示“该变量应该成为传递给此进程的环境的一部分,但在此之后不会保留下来。” - Bruno Bronosky
2-o posix 只适用于 bash,不适用于 sh - Dereckson
2这是不正确的。env或printenv只会打印环境变量。要获取在当前 shell 中声明的所有变量,请使用"declare -p"或"typeset -p"。请参阅本页面上的另一个答案。 - Florin Andrei
我喜欢这个关于Bash的答案,但是POSIX的set命令忽略了一些shell变量。你可以使用declare -p | while read -r _ flags line; do printf "%s\n" "$line"; done来获取它们全部。 - Colin Fraizer
顺便提一下,我使用以下命令进行了发现:diff <( set -o posix; set | while read -r line; do printf "%s\n" "${line%%=*}"; done | sort) <(declare -p | while read -r _ flags line; do printf "%s\n" "${line%%=*}"; done | sort) 来比较每个输出的差异。省略的变量包括:BASHPIDBASH_ARGV0EPOCH{REALTIME,SECONDS}FUNCNAMEHISTCMDLINENOOLDPWDRANDOMSECONDS - Colin Fraizer

您可以使用 declare 内建命令查看所有变量。
declare -p

如果你只对环境变量感兴趣,可以使用
declare -xp

运行help declare以查看其他选项。

5这是一个比POSIXLY_CORRECT=1 set更整洁的解决方案,值得一提的是,在这个上下文中,declaretypeset的别名,另一个bash内置命令。 - user359096
4这是正确的答案。 - Florin Andrei
2我认为这正是大多数人在寻找的东西。 - WinEunuuchs2Unix
为了方便起见,以下的Bash一行命令会打印出所有环境变量的名称:declare -xp | grep --perl-regexp --only-match '(?<=^declare -x )[^=]+' - maoizm
4如果你只想要变量名而不需要其他内容的话,使用compgen -e会更简单。 - geirha
也适用于ZSH,谢谢! - Alexey Vazhnov
如果你只想要变量的名称而不需要值,这是一个很有用的补充:declare -p | while read -r _ flags line; do printf "%s\n" "${line%%=*}"; done。(包含换行符的值,例如 IFS,会添加一行空白。) - Colin Fraizer
1@ColinFraizer 试试用 compgen -v 替代它 - geirha
1这很好。谢谢!(奇怪的是:当从顶层调用时,declare -p 包括 FUNCNAME,但 compgen -v 不包括。当在函数内部调用时,输出是相同的。) - Colin Fraizer
在zsh中,使用declare -p1来美化打印的变量,以提高可读性。 - smac89
如果我想要除了环境变量之外的所有变量,该怎么办? - Velkan
@Velkan 这有点困难,因为declarecompgen没有列出除环境变量以外的所有选项,但你可以通过获取所有变量名(compgen -v)并从中删除环境变量(compgen -e)来获得变量名列表。例如,使用comm -23 <(compgen -v) <(compgen -e) - geirha

我知道这个问题已经很旧并且已经回答了,但是我认为我可以添加一些有用的信息。

在上面描述的所有方法中,建议的过程是:

  • 启动终端
  • 使用envprintenv等显示环境变量

这些解决方案的问题是你正在查看终端中正在运行的shell的环境变量。你没有看到图形界面直接运行的应用程序可用的环境变量。

如果例如你使用~/.profile.bashrc.zshenv(取决于你的shell)来修改环境变量,比如将目录添加到路径中,那么这一点就会明显。

要查看直接在图形环境中启动的应用程序可用的环境变量,你可以执行以下操作(在Gnome Shell中,我确定其他DE中也有类似的方法):

  • 按下Alt-F2键
  • 运行命令xterm -e bash --noprofile --norc
(或者,如果你没有 xtermgnome-terminal -- bash --noprofile --norc --- 感谢 @Mike Nakis 的评论)。
现在你有一个终端,其中的 shell 没有添加任何环境变量。你可以使用 env 命令在这里列出所有的环境变量:

Example of the bare shell

明显地,新的 shell 将会拥有由系统文件添加的环境变量,但是这些变量应该通过继承可用于系统中的所有程序。 我发帖子是因为这已经是我第四次再次搜索这个技巧了,检查我的 .pam_environment 文件。所以现在我将更快地找到它(并且希望在此过程中帮助其他人...)

需要您拥有桌面环境,对于仅使用服务器命令行界面的人来说没有用处。 - K7AAY
7是的,但是对于仅命令行界面而言,之前的回答已经可以了。我只是想指出有时你需要检查图形环境启动的应用程序可用的环境变量,这和在终端中启动时看到的变量集不同。例如,如果你想弄清楚为什么你的 Kile 应用无法编译 LaTeX 文件,而在终端中可以,我在这里发布的技巧将会有很大帮助。 - Rmano
4非常感谢你提供的非常有用的答案!我刚刚从https://help.ubuntu.com/community/EnvironmentVariables#Desktop_environment_specifics链接到了它。 - Gunnar Hjalmarsson
谢谢。你是不是推荐 xterm -e bash --noprofile --norc,因为在 Ubuntu 开机时使用图形界面时,启动文件没有被读取和执行?请参考 https://askubuntu.com/q/1025845/1471 - Tim
@Tim 基本上,这只是一种在图形环境中仅使用环境变量而没有其他内容的方式。例如,标准终端会读取(或重新读取).bashrc 文件... - Rmano
2现在执行的正确命令(Ubuntu 18.04)是gnome-terminal -- bash --noprofile --norc - Mike Nakis
但是如果图形应用程序更改了它的环境变量(例如,由于某些设置),那么有没有办法通过进程的PID来检查任何进程的实际环境变量呢? - Arber
@Arber 我觉得这值得提出一个新问题... - Rmano

要在终端中列出环境变量,可使用键盘快捷键CTRL+ALT+T并输入env命令。
例如:
[raja@localhost ~]$ env
XDG_VTNR=1
SSH_AGENT_PID=3671
XDG_SESSION_ID=3
HOSTNAME=localhost.localdomain
IMSETTINGS_INTEGRATE_DESKTOP=yes
GPG_AGENT_INFO=/home/raja/.gnupg/S.gpg-agent:3691:1
GLADE_PIXMAP_PATH=:
TERM=xterm-256color
SHELL=/bin/bash
XDG_MENU_PREFIX=xfce-
DESKTOP_STARTUP_ID=
HISTSIZE=1000
XDG_SESSION_COOKIE=0250277dd805498381e96c05d88068b0-1364679772.845276-1676152201
WINDOWID=65011716
GNOME_KEYRING_CONTROL=/home/raja/.cache/keyring-N3QoQ2
IMSETTINGS_MODULE=none
QT_GRAPHICSSYSTEM_CHECKED=1
USER=raja

等等。

希望有所帮助。


我注意到环境变量缺少一些变量 o_O。尤其是在源文件VAR=VAL之后。 - ThorSummoner
3@ThorSummoner 这里的答案可能会有所帮助 https://stackoverflow.com/questions/15474650/unix-what-is-the-difference-between-source-and-export - georaldc

在bash中使用compgen:
compgen -v | while read line; do echo $line=${!line};done  

3这应该是被接受的答案,因为其他所有答案都列出了不仅仅是名称本身的内容。在我的情况下,一些变量包含多行值,这使得其他解决方案不可行。 - Mene
3一个变体:compgen -v | while read line; do declare -p $line; done - Eljay
@Eljay,declare -p和这个有什么区别? - DJCrashdummy
@DJCrashdummy вАҐ declare -p дЄНдЉЪеМЕжЛђиѓЄе¶В BASH_COMMAND, BASH_SUBSHELL, COMP_WORDBREAKS, HISTCMD, LINENO, RANDOM, SECONDS з≠ЙеЖЕеЃєгАВ - Eljay
@Eljay嗯...至少对我来说,declare -p "包括"或列出它们全部(并且还有FUNCNAME),但你说得没错:不显示值,而且数组的值也不显示。你知道为什么吗?—所以在我看来,你的行是最详尽的方法,甚至包括所有数组的值和索引! - DJCrashdummy
@DJCrashdummy • 我不知道为什么会这样。我猜测是那些东西的程序员认为这并不有用,因此才会有各种策略(或变通方法)来获取那些信息。 - Eljay

这里的大多数解决方案要么只打印环境变量,要么存在缺点,即env或(set -o posix; set)不以易于解析的形式打印值(尝试打印变量A = $'a \r\n b',它有多行...)。

这是一个函数,它将以POSIX转义形式打印所有变量,每个变量一行(对于简单文本变量有效,但不适用于数组):

function dump_vars {
    local VARNAME
    compgen -v | while read -r VARNAME; do
        printf "$VARNAME=%q\n" "${!VARNAME}"
    done
}

感谢 @tmgoblin 指出了使用 compgen -v 的用法。

如果你想要获取特定的环境变量,而不是用printenv打印所有的变量,你可以通过echo "$PWD"来打印特定的变量。

引号是不必要的,例如:echo $PATHecho $USER。这将打印环境变量的值。美元符号操作符是访问变量或命令值所需的唯一元素。 - nocarrier


已经在两年前提到过:http://askubuntu.com/a/276162/158442 - muru
@muru 没错。希望它能更好地展示env并进行更好的格式化,我已经添加了更多信息。 - Ciro Santilli OurBigBook.com
这就是编辑的用途。 - muru

  • printenv会显示所有全局环境变量
  • env,在登录修改后的全局环境变量
  • set,将显示所有本地环境变量,相对于会话(通常本地变量是全局变量加上会话特定的部分)

printenv 只列出已导出的变量, command+alt+$ ( "\e$": complete-variable ) 将列出所有变量。