Linux shell(bash/zsh) - 在特定目录下更改背景颜色

s5s*_*s5s 2 linux bash shell console zsh

我想在每次进入特定目录时更改shell的背景颜色(zsh但bash也会这样做).例如,我想在每次进入/ mnt/data时更改背景颜色以说明红色,如果我退出/ mnt/data /,则将其更改回正常状态...

要更改背景并保留当前提示,我会:

export PS1="$PS1 %{$'\e[0;41m'%}"
Run Code Online (Sandbox Code Playgroud)

我不知道如何挂起它以便每次更改工作目录时对其进行评估(包装在if语句中).

cho*_*oba 5

诀窍是在PS1中使用命令替换.bash中的以下类型的作品:

PS1='$(if [[ $PWD == /mnt/data* ]] ; then printf "\[\e[0;41m\]" ; else printf "\[\e[m\]" ; fi) %'
Run Code Online (Sandbox Code Playgroud)

通过"种类"我的意思是在更改到目录或从目录更改后立即在命令行上的行为有点奇怪(例如,在按Backspace后背景发生变化).

您还可以使用PROMPT_COMMAND变量,该变量比提示本身更适合代码:

PROMPT_COMMAND='if [[ $PWD == /mnt/data* ]] ; then printf "\e[0;41m" ; else printf "\e[m" ; fi'
Run Code Online (Sandbox Code Playgroud)

将代码保存在具有所有适当缩进的函数中更简洁,只需从变量中调用函数:

colour_mnt_data () {
    if [[ $PWD == /mnt/data* ]] ; then
        printf '\e[0;41m'
    else
        printf '\e[m'
    fi
}
PROMPT_COMMAND='colour_mnt_data'
Run Code Online (Sandbox Code Playgroud)


Ada*_*hon 5

的答案zsh(尽管第二部分可以适应bash):

这是一个两部分的问题:

  1. 作用于目录更改:对于zsh你可以使用chpwd钩子函数。每次更改当前工作目录时,都会调用数组中chpwd列出的任何函数chpwd_functions

    因此,如果您想对某些目录做出反应,则可以使用如下所示的内容

    # load helper function to manipulate hook arrays
    autoload -Uz add-zsh-hook
    
    # define hook function, decide on action based on $PWD, the new pwd.
    chback_on_chdir () {
        case $PWD in
            /mnt/data/* )
                # change background, when entering subdirectories of "/mnt/data"
                ;;
            /home )
                # change background, when entering exactly "/home"
                ;;
            /usr | /usr/* ) 
                # change background, when entering "/usr" or a subdirectory thereof
                ;;
            * )
                # change background, when entering any other directory
                ;;
        esac
    }
    
    # add chback_on_chdir to chpwd_functions
    add-zsh-hook chpwd chback_on_chdir
    
    Run Code Online (Sandbox Code Playgroud)
  2. 更改背景颜色:实际上,有两种方法可以更改背景颜色。

    • 您可以在终端内可用的颜色内更改以下打印字符的背景(这就是您在示例中所做的操作)。在zsh这种情况下可以这样做(简化了chdir钩子示例):

      # allow for parameter substitution in prompts
      setopt PROMPT_SUBST
      # add string `$COLOR` to $PS1. 
      # Note the `\` before `${COLOR}`, which prevents immediate evaluation.
      # `${COLOR}` will be substituted each time the prompt is printed
      PS1="$PS1\${COLOR}"
      
      chpwd () {
          case $PWD in
              /mnt/data/* )
                  # set background color to red
                  COLOR='%K{red}'
                  ;;
              * )
                  # reset background color to default
                  COLOR='%k'
                  # could also be just an empty string
                  #COLOR=''
                  # or unset
                  #unset COLOR
                  ;;
          esac
      }
      
      Run Code Online (Sandbox Code Playgroud)
    • 在某些(许多?)终端中,您还可以重新定义默认的背景色。实际上,这将改变各处的背景颜色,即使在已经打印的文本和“未打印”的位置上也是如此。这可以通过利用XTerm Control Sequences来完成,尽管它们的名称如此,但它也可以在其他终端仿真器中工作。(I与测试成功xtermurxvtgnome-terminaltermite)。有问题的控制顺序是

      ESC]11;<color>ST
      
      Run Code Online (Sandbox Code Playgroud)

      这里ESC是转义字符\e<color>是一种色彩规范(例如red#ff0000rgb:ff/00/00rgbi:1/0/0-什么实际工作可能取决于在终端上),并ST字符串结束 \e\\ESC\)。您可以将其发送到终端

      printf "\e]11;red\e\\"
      
      Run Code Online (Sandbox Code Playgroud)

      您可以使用控制顺序将颜色重置为配置的默认值

      ESC]111ST
      
      Run Code Online (Sandbox Code Playgroud)

      使用命令

      printf "\e]111\e\\"
      
      Run Code Online (Sandbox Code Playgroud)

      因此,如果您通常具有黑色背景,并且想在进入时/mnt/data或在其下的目录时将其设置为淡红色,则可以使用:

      chpwd () {
          case $PWD in
              /mnt/data | /mnt/data/* )
                  # set background color to a dark red
                  printf "\e]11;#1f0000\e\\"
                  ;;
              * )
                  # reset the background color to configured default
                  printf "\e]111\e\\"
                  ;;
          esac
      }
      
      Run Code Online (Sandbox Code Playgroud)

      注意:urxvt如果启用了透明性,我发现它似乎不起作用。

      可以通过将颜色规范替换为来检索当前值?

      printf "\e]11;?\e\\" ; sleep 1
      
      Run Code Online (Sandbox Code Playgroud)

      sleep 1需要,使输出不会立即被迅速覆盖。