繁体   English   中英

如何缩短命令行提示符的当前目录?

[英]How can I shortern my command line prompt's current directory?

我正在使用 Ubuntu,当我处理一些深层目录层次结构时,我厌倦了 bash 中的长提示。 所以,我想通过以下方式调整我的 PS1 以缩短工作目录部分:

目前我有:

pajton@dragon:~/workspace/projects/project1/folder1/test$

并希望拥有:

pajton@dragon:~/workspace/.../folder1/test$

如果 len($PWD) 超过给定的阈值,就会发生截断。 我想始终保留第一个路径组件和至少一个最后一个路径组件。 然后在空间允许的情况下,从右侧添加更多组件。

这就是我目前所拥有的。 它有效,但是:1)不保留第一个路径组件,2)不考虑边界处的切割路径:

pwd_length=14
pwd_symbol="..."
newPWD="${PWD/#$HOME/~}"

if [ $(echo -n $newPWD | wc -c | tr -d " ") -gt $pwd_length ]
then
   newPWD="...$(echo -n $PWD | sed -e "s/.*\(.\{$pwd_length\}\)/\1/")"
else
   newPWD="$(echo -n $PWD)"
fi

结果:

pajton@dragon:...sth/folder1/sample$ 

提前致谢!

对于寻找更简单的解决方案并且不需要路径中第一个目录的名称的人,Bash 使用PROMPT_DIRTRIM变量对此提供了内置支持。 从文档

PROMPT_DITRIM

如果设置为大于零的数字,则该值用作扩展 \\w 和 \\W 提示字符串转义时要保留的尾随目录组件的数量(请参阅打印提示)。 删除的字符将替换为省略号。

例如:

~$ mkdir -p a/b/c/d/e/f
~$ cd a/b/c/d/e/f
~/a/b/c/d/e/f$ export PROMPT_DIRTRIM=2
~/.../e/f$ PROMPT_DIRTRIM=3
~/.../d/e/f$ 

缺点:这取决于目录级别,而不是您可能不想要的路径长度。

优点:非常简单。 只需将export PROMPT_DIRTRIM=2添加到您的.bashrc

对于您的情况,请考虑使用 awk 而不是 sed 的此脚本:

pwd_length=14
pwd_symbol="..."
newPWD="${PWD/#$HOME/~}"
if [ $(echo -n $newPWD | wc -c | tr -d " ") -gt $pwd_length ]
then
   newPWD=$(echo -n $newPWD | awk -F '/' '{
   print $1 "/" $2 "/.../" $(NF-1) "/" $(NF)}')
fi
PS1='${newPWD}$ '

对于目录~/workspace/projects/project1/folder1/test的示例,它使 PS1 为: ~/workspace/.../folder1/test

更新

上述解决方案将设置您的提示,但正如您在评论中指出的那样,当您更改目录时,它不会动态更改 PS1。 因此,这是在您更改目录时动态设置 PS1 的解决方案。

将这两行放在您的 .bashrc 文件中:

export MYPS='$(echo -n "${PWD/#$HOME/~}" | awk -F "/" '"'"'{
if (length($0) > 14) { if (NF>4) print $1 "/" $2 "/.../" $(NF-1) "/" $NF;
else if (NF>3) print $1 "/" $2 "/.../" $NF;
else print $1 "/.../" $NF; }
else print $0;}'"'"')'
PS1='$(eval "echo ${MYPS}")$ '

awk 中的if (NF > 4 && length($0) > 14)条件只会在当前目录深度超过 3 个目录时应用特殊处理,并且如果$PWD长度超过 14 个字符,否则它将保持 PS1 为$PWD

例如:如果当前目录是~/workspace/projects/project1$那么 PS1 将是~/workspace/projects/project1$

.bashrc 中的上述效果在您的 PS1 上将如下所示:

~$ cd ~/workspace/projects/project1/folder1/test
~/workspace/.../folder1/test$ cd ..
~/workspace/.../project1/folder1$ cd ..
~/workspace/.../project1$ cd ..
~/.../projects$ cd ..
~/workspace$ cd ..
~$

请注意当我更改目录时提示如何更改。 如果这不是您想要的,请告诉我。

这是我根据 anubhava 的解决方案使用的。 它设置提示和窗口标题。 awk 脚本更具可读性,因此可以轻松调整/自定义。

如果路径超过 16 个字符和 4 层深,它将折叠路径。 此外,它还会在 ... 中显示折叠了多少个目录,以便您了解路径的深度,即: ~/usr/..4../path2/path1表示折叠了 4 个级别。

# define the awk script using heredoc notation for easy modification
MYPSDIR_AWK=$(cat << 'EOF'
BEGIN { FS = OFS = "/" }
{ 
   sub(ENVIRON["HOME"], "~");
   if (length($0) > 16 && NF > 4)
      print $1,$2,".." NF-4 "..",$(NF-1),$NF
   else
      print $0
}
EOF
)

# my replacement for \w prompt expansion
export MYPSDIR='$(echo -n "$PWD" | awk "$MYPSDIR_AWK")'

# the fancy colorized prompt: [0 user@host ~]$
# return code is in green, user@host is in bold/white
export PS1='[\[\033[1;32m\]$?\[\033[0;0m\] \[\033[0;1m\]\u@\h\[\033[0;0m\] $(eval "echo ${MYPSDIR}")]$ '

# set x/ssh window title as well
export PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME%%.*} $(eval "echo ${MYPSDIR}")\007"'

这是它的实际运行情况。 绿色的 0 是最后一条命令的返回码:

在此处输入图片说明

echo -n $PWD | sed -re "s|(~?/[^/]*/).*(.{$pwd_length})|\1...\2|"

sed 与 -r 仅为方便起见,允许省略括号前的反斜杠和“|” 作为分隔符也只是为了方便 - 因为我们想在命令中使用斜杠。 我猜你的 home get 也显示为 ~,所以 ~/foo/bar/baz/ 应该以 ~/foo/.../baz 结尾,/foo/bar/baz/ 为 /foo/.../baz /.

所以我们取一个可选的~,然后是斜杠,名称,斜杠是\\1,然后是something,然后是\\2。

另一种方法,仍然使用sedawk来生成提示。 这会将您的$HOME目录转换为 ~,显示您的根目录、最低级别(当前目录)及其父目录,中间的每个目录用..分隔。

.bashrc (或 OS X 上的.bash_profile )中:

function generate_pwd {
  pwd | sed s.$HOME.~.g | awk -F"/" '
  BEGIN { ORS="/" }
  END {
  for (i=1; i<= NF; i++) {
      if ((i == 1 && $1 != "") || i == NF-1 || i == NF) {
        print $i
      }
      else if (i == 1 && $1 == "") {
        print "/"$2
        i++
      }
      else {
        print ".."
      }
    }
  }'
}
export PS1="\$(generate_pwd) -> "

该脚本使用 awk 的内置NF变量(字段数)和位置变量( $1, $2 ... )来打印由ORS变量(输出记录分隔符)分隔的每个字段(目录名称)。 它会在您的提示中将内部目录折叠为..

它的使用示例:

~/ -> cd Documents/
~/Documents/ -> cd scripts/
~/Documents/scripts/ -> cd test1/
~/../scripts/test1/ -> cd test2
~/../../test1/test2/ -> pwd
/Users/Brandon/Documents/scripts/test1/test2
~/../../test1/test2/ -> cd test3/
~/../../../test2/test3/ -> cd test4/
~/../../../../test3/test4/ -> pwd
/Users/Brandon/Documents/scripts/test1/test2/test3/test4
~/../../../../test3/test4/ -> cd /usr/
/usr/ -> cd local/
/usr/local/ -> cd etc/
/usr/local/etc/ -> cd openssl/
/usr/../etc/openssl/ -> cd private/
/usr/../../openssl/private/ ->

除了使用PROMPT_DIRTRIM的 bash 内置解决方案PROMPT_DIRTRIM ,您可能还想尝试$(pwd | tail -c16) ,它比大多数其他答案简单一点,但只提供当前目录的最后 16 个字符。 当然,用你想要的任何数字替换 16。

为什么不直接使用${string:position:length} 您可以执行${string:-$max_chars}以获得${string:-$max_chars}的最后${max_chars}

注意负值

与以前的解决方案没有太大区别。 但是,也许更具可读性/可编辑性。 但是没有解决文件夹名称边界的问题,只关注提示的长度。

### SET MY PROMPT ###
if [ -n "$PS1" ]; then
    # A temporary variable to contain our prompt command
    NEW_PROMPT_COMMAND='
        pwd_short=${PWD/#$HOME/\~};
        if [ ${#pwd_short} -gt 53 ]; then
            TRIMMED_PWD=${pwd_short: 0: 25}...${pwd_short: -25}
        else
            TRIMMED_PWD=${pwd_short}
        fi
    '

    # If there's an existing prompt command, let's not 
    # clobber it
    if [ -n "$PROMPT_COMMAND" ]; then
        PROMPT_COMMAND="$PROMPT_COMMAND;$NEW_PROMPT_COMMAND"
    else
        PROMPT_COMMAND="$NEW_PROMPT_COMMAND"
    fi

    # We're done with our temporary variable
    unset NEW_PROMPT_COMMAND

    # Set PS1 with our new variable
    # \h - hostname, \u - username
    PS1='\u@\h: $TRIMMED_PWD\$ '
fi

添加到 .bashrc 文件中。 提示的所有部分都已正确更新。 如果你在你的主目录中,第一部分会被缩短。 例子:

用户@计算机:~/misc/projs/solardrivers...src/com/mycompany/handles$

generatePwd(){
  set -- "`pwd | sed -e s.${HOME}.~.g`"
  IFS="/"; declare -a array=($*)
  srt=""
  count=0
  for i in ${!array[@]}; do
      # echo ${array[i]} - $i/${#array[@]}
      if [[ $i == 0 ]]; then
        srt+=""
      elif [[ $i == $((${#array[@]}-1)) ]] || [[ $i == $((${#array[@]}-2)) ]]; then
          srt+="/${array[i]}"
      else
        count=$((${count}+1))
      fi
  done
  if [[ $count != 0 ]]; then
    srt="${array[0]}/.$count.$srt"
  else
    srt="${array[0]}$srt"
  fi
  echo "${srt}"
}

导出 PS1

PS1="\$(generatePwd)"

安慰

$ ~/.3./machine-learning/deep-learning-computer-vision

https://github.com/chrissound/SodiumSierraStrawberry

允许您截断路径,如:

来自:/home/sodium/Projects/Personal/Sierra/Super/Long/Path/HolyAvacado

至:»项目/Sie.../Sup.../Lon.../Pat.../HolyAvacado/

Raychi 的回答在 Mac / Catalina 上对我很有用。

稍微修改了相应的部分,以“两深”开头。

if (length($0) > 16 && NF > 5)
   print $1,$2,$3,".." NF-5 "..",$(NF-1),$NF

结果将类似于:

/Volumes/Work/..3../Python/Tutorials

我的 .bashrc 文件的相关部分作为自包含的复制和粘贴解决方案是:

MYPSDIR_AWK=$(cat << 'EOF'
BEGIN { FS = OFS = "/" }
{
   sub(ENVIRON["HOME"], "~");
   if (length($0) > 16 && NF > 5)
      print $1,$2,$3,".." NF-5 "..",$(NF-1),$NF
   else
      print $0
}
EOF
)

export MYPSDIR='$(echo -n "$PWD" | awk "$MYPSDIR_AWK")'

请注意,以上不包括Raychi 的着色方案。 如果需要,请单独添加。

我建议改编我见过的一个小脚本:

function generate_pwd { 
pwd | awk -F/ 'BEGIN{ ORS="/" } END{for (i=1; i<=NF; i++){print substr($i,1,1)}}' 
}
export PS1="\$(generate_pwd) => "

你在你的 bashrc 中添加这些几行并且它工作......正常:

/d/m/r/S/ => pwd
/d/montreui/rpmbuild/SOURCES

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM