Bash - обновить заголовок терминала, выполнив вторую команду
На моем терминале в Ubuntu я часто запускаю программы, которые работают в течение длительного времени. И поскольку таких программ много, я забываю, какой терминал для какой программы, если я не перечислил все эти. Поэтому я хотел найти способ обновить заголовок терминала до имени программы, всякий раз, когда я запускаю команду. Я не хочу делать это вручную.
Я использую gnome-terminal, но ответ не должен зависеть от этого. В принципе, если я могу запустить вторую команду, тогда я могу просто использовать команду gconftool для обновления заголовка. Поэтому я надеялся найти способ захватить команду в bash и обновить заголовок после каждой команды. Как мне это сделать?
Ответы
Ответ 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.