Подтвердить что ты не робот

Bash - обновить заголовок терминала, выполнив вторую команду

На моем терминале в Ubuntu я часто запускаю программы, которые работают в течение длительного времени. И поскольку таких программ много, я забываю, какой терминал для какой программы, если я не перечислил все эти. Поэтому я хотел найти способ обновить заголовок терминала до имени программы, всякий раз, когда я запускаю команду. Я не хочу делать это вручную.

Я использую gnome-terminal, но ответ не должен зависеть от этого. В принципе, если я могу запустить вторую команду, тогда я могу просто использовать команду gconftool для обновления заголовка. Поэтому я надеялся найти способ захватить команду в bash и обновить заголовок после каждой команды. Как мне это сделать?

4b9b3361

Ответ 1

У меня есть для вас несколько ответов:) Вы правы, что не важно, что вы используете gnome-terminal, но имеет значение, какую оболочку вы используете. Это намного проще в zsh, но в дальнейшем я предполагаю, что вы используете bash, и это довольно недавняя версия ( > 3.1).

Прежде всего:

Какую переменную среды содержат текущую "команду"?

Существует переменная окружения, которая имеет более или менее то, что вы хотите - $BASH_COMMAND. Там только одна маленькая зацепка, которая заключается в том, что она покажет вам последнюю команду в трубе. Я не уверен на 100%, что он будет делать с комбинациями подоболочек, либо:)

Итак, я надеялся найти способ захватить команду в bash и обновить название после каждой команды.

Я думал об этом, и теперь, когда я понимаю, что вы хотите сделать, я понял, что реальная проблема заключается в том, что вам нужно обновить заголовок до каждой команды. Это означает, что переменные окружения $PROMPT_COMMAND и $PS1 недоступны, поскольку они выполняются только после. Команда возвращает.

В bash, единственный способ, которым я могу думать, добиться того, чего вы хотите, - (ab) использовать СИГНАЛ DEBUG. Итак, вот решение - поместите это в конце вашего .bashrc:

trap 'printf "\033]0;%s\007" "${BASH_COMMAND//[^[:print:]]/}"' DEBUG

Чтобы обойти проблему с трубами, я общался с этим:

function settitle () {
    export PREV_COMMAND=${PREV_COMMAND}${@}
    printf "\033]0;%s\007" "${BASH_COMMAND//[^[:print:]]/}"
    export PREV_COMMAND=${PREV_COMMAND}' | '
}

export PROMPT_COMMAND=${PROMPT_COMMAND}';export PREV_COMMAND=""'

trap 'settitle "$BASH_COMMAND"' DEBUG

но я не обещаю этого совершенного!

Ответ 2

Попробуйте следующее:

trap 'echo -ne "\033]2;$(history 1 | sed "s/^[ ]*[0-9]*[ ]*//g")\007"' DEBUG

Благодаря history 1 он работает даже со сложными выражениями, например:

true && (false); echo $? | cat

Для каких подходов, основанных на $BASH_COMMAND или [email protected], сбой. Например, simon отображает:

true | echo $? | cat

Благодаря Gilles и simon для вдохновения.

Ответ 3

Я вижу, что стати пытается сделать, за исключением того, что это намного больше, чем нужно. И не вызывает всевозможные другие потенциально плохие вещи, которые могут возникнуть в результате переопределения "cd" и помещения всего этого тестирования только для изменения каталогов. Bash имеет большую поддержку.

Вы можете поместить это в свой .bashrc где угодно после того, как вы установите текущую подсказку PS1 (таким образом она просто добавляет ее)

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

Ответ 4

Я делаю что-то вроде этого, чтобы показать мой pwd в заголовке, который можно изменить, чтобы делать все, что вы хотите сделать с заголовком:

function title { echo -en "\033]2;$1\007"; }
function cd { dir=$1; if [ -z "$dir" ]; then dir=~; fi; builtin cd "$dir" && title `pwd`; }

Я просто бросил это в свой ~/.bash_aliases.

Update

Я столкнулся с странными ошибками с моим оригинальным ответом. Я в конечном итоге выделил по умолчанию Ubuntu PS1 и разбил его на части только для того, чтобы реализовать одну из частей:

# simple prompt
COLOR_YELLOW_BOLD="\[\033[1;33m\]"
COLOR_DEFAULT="\[\033[0m\]"
TITLE="\[\e]0;\[email protected]\h:\w\a\]"
PROMPT="\w\n$ "
HUH="${debian_chroot:+($debian_chroot)}"
PS1="${COLOR_YELLOW_BOLD}${TITLE}${HUH}${PROMPT}${COLOR_DEFAULT}"

Без разбиения на переменные это будет выглядеть так:

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

Ответ 5

OP запросил bash, но другим может быть интересно узнать, что (как упоминалось выше) это действительно намного проще с помощью оболочки zsh, Пример:

# Set window title to command just before running it.
preexec() { printf "\x1b]0;%s\x07" "$1"; }

# Set window title to current working directory after returning from a command.
precmd() { printf "\x1b]0;%s\x07" "$PWD" }

В preexec, $1 содержит команду как введенную (требуется, чтобы история оболочки была включена, что кажется справедливым допущением), $2 расширенная команда (псевдонимы оболочки и т.д.) и $3 "очень расширенная" команда (тела функции оболочки). (подробнее)

Ответ 6

Вы можете настроить bash так, чтобы он посылал определенную escape-последовательность на терминал каждый раз, когда запускает внешнюю программу. Если вы используете escape-последовательность, которую используют терминалы для обновления своих заголовков, ваша проблема должна быть решена.

Я использовал это раньше, поэтому я знаю, что это возможно. но я не могу вспомнить это с головы до головы, но у меня нет времени исследовать детали прямо сейчас.

Ответ 7

Основываясь на необходимости окна автоматической установки шлейфа, я изменил свой файл /etc/bash.bashrc в системе Debian/Ubuntu. Я опубликовал полное содержимое для полноты, но соответствующий бит начинается с строки комментария # Display command ....

# 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)}\[email protected]\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
            *\033]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 "\033]0;${USER}@${HOSTNAME}: ${BASH_COMMAND}\007"
                ;;
        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 [email protected]:dir
#case "$TERM" in
#xterm*|rxvt*)
#    PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"'
#    ;;
#*)
#    ;;
#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 -- "$1"
                   return $?
                elif [ -x /usr/share/command-not-found/command-not-found ]; then
                   /usr/bin/python /usr/share/command-not-found/command-not-found -- "$1"
                   return $?
                else
                   printf "%s: command not found\n" "$1" >&2
                   return 127
                fi
        }
fi

Ответ 8

Я проверил три метода, все в порядке, используйте любой для вашего удовольствия.

export PROMPT_COMMAND='echo -ne "\033]2;$(history 1 | sed "s/^[ ]*[0-9]*[ ]*//g")\007"'

trap 'echo -ne "\033]2;$(history 1 | sed "s/^[ ]*[0-9]*[ ]*//g")\007"' DEBUG

trap 'echo -ne "\e]0;"; echo -n $BASH_COMMAND; echo -ne "\a"' DEBUG

обратите внимание, что если вы используете $BASH_COMMAND, он не распознает псевдоним bash и использует команду PROMPT_COMMAND show finished, но используйте команду show show running.