Linux Bash - 通过运行第二个命令更新终端标题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5076127/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 02:58:03  来源:igfitidea点击:

Bash - Update terminal title by running a second command

linuxbashshellterminal

提问by Neo

On my terminal in Ubuntu, I often run programs which keep running for a long time. And since there are a lot of these programs, I keep forgetting which terminal is for which program, unless I tab through all of those. So I wanted to find a way to update my terminal title to the program name, whenever I run a command. I don't want to do it manually.

在我的 Ubuntu 终端上,我经常运行长时间运行的程序。而且由于有很多这样的程序,我总是忘记哪个终端用于哪个程序,除非我浏览所有这些程序。所以我想找到一种方法,每当我运行命令时,将我的终端标题更新为程序名称。我不想手动完成。

I use gnome-terminal, but answer shouldn't really depend on that. Basically, If I'm able to run a second command, then I can simply use gconftool command to update the title. So I was hoping to find a way to capture the command in bash and update the title after every command. How do I do that?

我使用 gnome-terminal,但答案不应该真正依赖于此。基本上,如果我能够运行第二个命令,那么我可以简单地使用 gconftool 命令来更新标题。所以我希望找到一种方法来捕获 bash 中的命令并在每个命令之后更新标题。我怎么做?

采纳答案by simon

I have some answers for you :) You're right that it shouldn't matter that you're using gnome-terminal, but it does matter what command shell you're using. This is a lot easier in zsh, but in what follows I'm going to assume you're using bash, and that it's a fairly recent version (> 3.1).

我有一些答案给你 :) 你是对的,你使用 gnome-terminal 并不重要,但你使用的是什么命令 shell 确实很重要。这是一个容易得多zsh,但在下面我将假设你使用bash,而且它是一个相当新的版本(> 3.1)。

First of all:

首先:

Which environment variable would contain the current 'command'?

哪个环境变量将包含当前的“命令”?

There is an environment variable which has more-or-less what you want - $BASH_COMMAND. There's only one small hitch, which is that it will only show you the last command in a pipe. I'm not 100% sure what it will do with combinations of subshells, either :)

有一个环境变量或多或少有你想要的 - $BASH_COMMAND。只有一个小问题,那就是它只会显示管道中的最后一个命令。我也不是 100% 确定它会用子外壳的组合做什么:)

So I was hoping to find a way to capture the command in bash and update the title after every command.

所以我希望找到一种方法来捕获 bash 中的命令并在每个命令之后更新标题。

I've been thinking about this, and now that I understand what you want to do, I realized the real problem is that you need to update the title beforeevery command. This means that the $PROMPT_COMMANDand $PS1environment variables are out as possible solutions, since they're only executed afterthe command returns.

我一直在考虑这个,现在我明白你想要做什么,我意识到真正的问题是你需要每个命令之前更新标题。这意味着$PROMPT_COMMAND$PS1环境变量是可能的解决方案,因为它们仅命令返回执行。

In bash, the only way I can think of to achieve what you want is to (ab)use the DEBUG SIGNAL. So here's a solution -- stick this at the end of your .bashrc:

bash,我能想到的唯一方法是(ab)使用调试信号。所以这是一个解决方案——把它放在你的末尾.bashrc

trap 'printf "3]0;%s
function settitle () {
    export PREV_COMMAND=${PREV_COMMAND}${@}
    printf "3]0;%s
trap 'echo -ne "3]2;$(history 1 | sed "s/^[ ]*[0-9]*[ ]*//g")
true && (false); echo $? | cat
7"' DEBUG
7" "${BASH_COMMAND//[^[:print:]]/}" export PREV_COMMAND=${PREV_COMMAND}' | ' } export PROMPT_COMMAND=${PROMPT_COMMAND}';export PREV_COMMAND=""' trap 'settitle "$BASH_COMMAND"' DEBUG
7" "${BASH_COMMAND//[^[:print:]]/}"' DEBUG

To get around the problem with pipes, I've been messing around with this:

为了解决管道问题,我一直在搞这个:

true | echo $? | cat

but I don't promise it's perfect!

但我不保证它是完美的!

回答by ndim

You can set up bashsuch that it sends a certain escape sequence to the terminal every time it starts an external program. If you use the escape sequence that terminals use to update their titles, your problem should be solved.

您可以设置bash为每次启动外部程序时都会向终端发送特定的转义序列。如果您使用终端用于更新其标题的转义序列,则应该可以解决您的问题。

I have used that before, so I know it is possible. but I cannot remember it off the top of my head and do not have time to research the details right now, though.

我以前用过,所以我知道这是可能的。但我记不得它了,现在也没有时间研究细节。

回答by John Mellor

Try this:

尝试这个:

function title { echo -en "3]2;
# simple prompt
COLOR_YELLOW_BOLD="\[3[1;33m\]"
COLOR_DEFAULT="\[3[0m\]"
TITLE="\[\e]0;\u@\h:\w\a\]"
PROMPT="\w\n$ "
HUH="${debian_chroot:+($debian_chroot)}"
PS1="${COLOR_YELLOW_BOLD}${TITLE}${HUH}${PROMPT}${COLOR_DEFAULT}"
7"; } function cd { dir=; if [ -z "$dir" ]; then dir=~; fi; builtin cd "$dir" && title `pwd`; }

Thanks to the history 1it works even with complicated expressions like:

由于history 1它甚至可以使用复杂的表达式,例如:

PS1="\[3[1;33m\]\[\e]0;\u@\h:\w\a\]${debian_chroot:+($debian_chroot)}\w\n$ \[3[0m\]"

For which approaches relying on $BASH_COMMAND or $@ fail. For example simon's displays:

对于依赖 $BASH_COMMAND 或 $@ 的方法失败。例如simon的显示:

# If this is an xterm set the titlebar to user@host:dir
case "$TERM" in
xterm*|rxvt*)
    PS1="\[\e]0;\u@\h: \w\a\]$PS1"
    ;;
*)
    ;;
esac

Thanks to Gillesand simon for providing inspiration.

感谢Gilles和 simon 提供的灵感。

回答by Stoutie

I'm doing something like this, to show my pwdin the title, which could be modified to do whatever you want to do with the title:

我正在做这样的事情,以pwd在标题中显示我的内容,可以对其进行修改以执行您想要对标题执行的任何操作:

# System-wide .bashrc file for interactive bash(1) shells.

# To enable the settings / commands in this file for login shells as well,
# this file has to be sourced in /etc/profile.

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize

# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
    debian_chroot=$(cat /etc/debian_chroot)
fi

# set a fancy prompt (non-color, overwrite the one in /etc/profile)
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w$ '

# Display command run in title which allows us to distinguish Kitty/Putty
# windows and re-position easily using AutoSizer window utility. Based on a
# post here: http://mg.pov.lt/blog/bash-prompt.html
case "$TERM" in
xterm*|rxvt*)
    # Show the currently running command in the terminal title:
    # http://www.davidpashley.com/articles/xterm-titles-with-bash.html
    show_command_in_title_bar()
    {
        case "$BASH_COMMAND" in
            *3]0*)
                # The command is trying to set the title bar as well;
                # this is most likely the execution of $PROMPT_COMMAND.
                # In any case nested escapes confuse the terminal, so don't
                # output them.
                ;;
            *)
                echo -ne "3]0;${USER}@${HOSTNAME}: ${BASH_COMMAND}
# Set window title to command just before running it.
preexec() { printf "\x1b]0;%s\x07" ""; }

# Set window title to current working directory after returning from a command.
precmd() { printf "\x1b]0;%s\x07" "$PWD" }
7" ;; esac } trap show_command_in_title_bar DEBUG ;; *) ;; esac # Commented out, don't overwrite xterm -T "title" -n "icontitle" by default. # If this is an xterm set the title to user@host:dir #case "$TERM" in #xterm*|rxvt*) # PROMPT_COMMAND='echo -ne "3]0;${USER}@${HOSTNAME}: ${PWD}
export PROMPT_COMMAND='echo -ne "3]2;$(history 1 | sed "s/^[ ]*[0-9]*[ ]*//g")##代码##7"'

trap 'echo -ne "3]2;$(history 1 | sed "s/^[ ]*[0-9]*[ ]*//g")##代码##7"' DEBUG

trap 'echo -ne "\e]0;"; echo -n $BASH_COMMAND; echo -ne "\a"' DEBUG
7"' # ;; #*) # ;; #esac # enable bash completion in interactive shells if ! shopt -oq posix; then if [ -f /usr/share/bash-completion/bash_completion ]; then . /usr/share/bash-completion/bash_completion elif [ -f /etc/bash_completion ]; then . /etc/bash_completion fi fi # if the command-not-found package is installed, use it if [ -x /usr/lib/command-not-found -o -x /usr/share/command-not-found/command-not-found ]; then function command_not_found_handle { # check because c-n-f could've been removed in the meantime if [ -x /usr/lib/command-not-found ]; then /usr/bin/python /usr/lib/command-not-found -- "" return $? elif [ -x /usr/share/command-not-found/command-not-found ]; then /usr/bin/python /usr/share/command-not-found/command-not-found -- "" return $? else printf "%s: command not found\n" "" >&2 return 127 fi } fi

I just threw this in my ~/.bash_aliases.

我只是把这个扔进了我的~/.bash_aliases.

Update

更新

I ran into strange bugs with my original answer. I ended up picking apart the default Ubuntu PS1 and breaking it into parts only to realize one of the parts was the title:

我的原始答案遇到了奇怪的错误。我最终将默认的 Ubuntu PS1 拆开并将其分解为多个部分,结果发现其中一个部分是标题:

##代码##

Without breaking into variables, it would look like this:

在不分解变量的情况下,它看起来像这样:

##代码##

回答by UpAndAdam

I see what stoutie is trying to do, except it's a lot more work than needed. And doesn't cause all sorts of other potentially bad things that can occur as a result of redefining 'cd' and putting in all of that testing just to change directories. Bash has built in support for most of this.

我明白 stoutie 正在尝试做什么,除了它比需要的工作要多得多。并且不会导致由于重新定义“cd”并进行所有测试只是为了更改目录而可能发生的各种其他潜在的坏事。Bash 内置了对其中大部分内容的支持。

You can put this in your .bashrc anywhere after you set your current PS1 prompt (this way it just prepends it)

在设置当前的 PS1 提示后,您可以将它放在 .bashrc 中的任何位置(这样它只是在前面)

##代码##

回答by Daniel Sokolowski

Based on the the need to auto position putty windowsI have modified my /etc/bash.bashrcfile on a Debian/Ubuntu system. I have posted the full contents for completeness but the relevant bit to starts on the # Display command ...comment line.

基于自动定位腻子窗口的需要,我/etc/bash.bashrc在 Debian/Ubuntu 系统上修改了我的文件。为了完整起见,我已经发布了全部内容,但相关的部分要从# Display command ...评论行开始。

##代码##

回答by S?ren L?vborg

The OP asked for bash, but others might be interested to learn that (as mentioned above) this is indeed a lot easier using the zshshell. Example:

OP 要求bash,但其他人可能有兴趣了解(如上所述)使用zshshell确实容易得多。例子:

##代码##

In preexec, $1contains the command as typed (requires shell history to be enabled, which seems to be a fair assumption), $2the expanded command (shell aliases etc.) and $3the "very expanded" command (shell function bodies). (more)

preexec, 中$1包含键入的命令(需要启用 shell 历史记录,这似乎是一个合理的假设)、$2扩展命令(shell 别名等)和$3“非常扩展”命令(shell 函数体)。(更多的)

回答by netawater

I have tested three method, all is OK, use any one for your pleasure.

我已经测试了三种方法,都可以,使用任何一种方法都可以。

##代码##

please note if use $BASH_COMMAND, it don't recognize bash alias, and use PROMPT_COMMAND show finished command, but use trap show running command.

请注意,如果使用 $BASH_COMMAND,它不识别 bash 别名,而使用 PROMPT_COMMAND show finished 命令,而使用 trap show running 命令。