Bash - обновить заголовок терминала, выполнив вторую команду - PullRequest
22 голосов
/ 22 февраля 2011

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

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

Ответы [ 8 ]

21 голосов
/ 22 февраля 2011

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

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

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

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

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

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

В bash единственный способ, которым я могу придумать, чтобы достичь того, чего вы хотите, - это (а) использовать СИГНАЛ ОТЛАДКИ. Итак, вот решение - прикрепите это в конце вашего .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

но я не обещаю, что он идеален!

12 голосов
/ 18 августа 2011

Попробуйте это:

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

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

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

Для каких подходов полагаться на $ BASH_COMMAND или $ @ fail. Например, simon отображает:

true | echo $? | cat

Спасибо Жилю и Саймону за вдохновение.

6 голосов
/ 09 ноября 2012

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

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

# 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
2 голосов
/ 16 января 2014

ОП запросил 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 «очень расширенная» команда (тела функций оболочки). (больше)

1 голос
/ 01 августа 2012

Я делаю что-то вроде этого, чтобы показать мой 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.

Обновление

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

# simple prompt
COLOR_YELLOW_BOLD="\[\033[1;33m\]"
COLOR_DEFAULT="\[\033[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}"

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

PS1="\[\033[1;33m\]\[\e]0;\u@\h:\w\a\]${debian_chroot:+($debian_chroot)}\w\n$ \[\033[0m\]"
0 голосов
/ 11 ноября 2015

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

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 complete, но использует команду trap show running.

0 голосов
/ 11 декабря 2013

Исходя из необходимости автоматического позиционирования окон Я изменил свой файл /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)}\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
            *\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 user@host: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
0 голосов
/ 22 февраля 2011

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...