巴什PWD缩短(Bash PWD Shortening)

2019-08-31 21:35发布

我在寻找一个bash的功能,这将缩短长路径名,以保持我的PS1变量从得到过长。 沿着线的东西:

/this/is/the/path/to/a/really/long/directory/i/would/like/shortened

可能最终为:

/t../i../t../p../to/a/r../l../d../i/w../like/shortened

东西拿了路径和字符的最大可接受数缩短将是完美的我的.bashrc文件。

Answer 1:

如何Python脚本? 这将缩短第一时间最长的目录名,在直至符合其长度的目标或无法获得任何路径短的时间一个字符。 它不会缩短路径中的最后一个目录。

(我开始在普通的shell脚本,但男人写这篇时,bash太臭在字符串操作。)

#!/usr/bin/env python
import sys

try:
    path   = sys.argv[1]
    length = int(sys.argv[2])
except:
    print >>sys.stderr, "Usage: $0 <path> <length>"
    sys.exit(1)

while len(path) > length:
    dirs = path.split("/");

    # Find the longest directory in the path.
    max_index  = -1
    max_length = 3

    for i in range(len(dirs) - 1):
        if len(dirs[i]) > max_length:
            max_index  = i
            max_length = len(dirs[i])

    # Shorten it by one character.    
    if max_index >= 0:
        dirs[max_index] = dirs[max_index][:max_length-3] + ".."
        path = "/".join(dirs)

    # Didn't find anything to shorten. This is as good as it gets.
    else:
        break

print path

示例输出:

$ echo $DIR
/this/is/the/path/to/a/really/long/directory/i/would/like/shortened
$ ./shorten.py $DIR 70
/this/is/the/path/to/a/really/long/directory/i/would/like/shortened 
$ ./shorten.py $DIR 65
/this/is/the/path/to/a/really/long/direc../i/would/like/shortened
$ ./shorten.py $DIR 60
/this/is/the/path/to/a/re../long/di../i/would/like/shortened
$ ./shorten.py $DIR 55
/t../is/the/p../to/a/r../l../di../i/wo../like/shortened
$ ./shorten.py $DIR 50
/t../is/the/p../to/a/r../l../d../i/w../l../shortened


Answer 2:

不会产生相同的结果,但我~/.bashrc包含

_PS1 ()
{
    local PRE= NAME="$1" LENGTH="$2";
    [[ "$NAME" != "${NAME#$HOME/}" || -z "${NAME#$HOME}" ]] &&
        PRE+='~' NAME="${NAME#$HOME}" LENGTH=$[LENGTH-1];
    ((${#NAME}>$LENGTH)) && NAME="/...${NAME:$[${#NAME}-LENGTH+4]}";
    echo "$PRE$NAME"
}
PS1='\u@\h:$(_PS1 "$PWD" 20)\$ '

这限制了显示出最多20个字符的路径。 如果路径是超过20个字符,将示出像/...d/like/shortened~/.../like/shortened



Answer 3:

这里有一个唯一的bash的解决方案,你可能会喜欢。 这将缩短到仍然可以制表完成最短前缀的路径的各个部分,并用*代替。作为填充物。

#!/bin/bash

begin="" # The unshortened beginning of the path.
shortbegin="" # The shortened beginning of the path.
current="" # The section of the path we're currently working on.
end="${2:-$(pwd)}/" # The unmodified rest of the path.
end="${end#/}" # Strip the first /
shortenedpath="$end" # The whole path, to check the length.
maxlength="${1:-0}"

shopt -q nullglob && NGV="-s" || NGV="-u" # Store the value for later.
shopt -s nullglob    # Without this, anything that doesn't exist in the filesystem turns into */*/*/...

while [[ "$end" ]] && (( ${#shortenedpath} > maxlength ))
do
  current="${end%%/*}" # everything before the first /
  end="${end#*/}"    # everything after the first /

  shortcur="$current"
  shortcurstar="$current" # No star if we don't shorten it.

  for ((i=${#current}-2; i>=0; i--))
  do
    subcurrent="${current:0:i}"
    matching=("$begin/$subcurrent"*) # Array of all files that start with $subcurrent. 
    (( ${#matching[*]} != 1 )) && break # Stop shortening if more than one file matches.
    shortcur="$subcurrent"
    shortcurstar="$subcurrent*"
  done

  begin="$begin/$current"
  shortbegin="$shortbegin/$shortcurstar"
  shortenedpath="$shortbegin/$end"
done

shortenedpath="${shortenedpath%/}" # strip trailing /
shortenedpath="${shortenedpath#/}" # strip leading /

echo "/$shortenedpath" # Make sure it starts with /

shopt "$NGV" nullglob # Reset nullglob in case this is being used as a function.

给它的长度作为第一个参数,以及路径作为第二个可选参数。 如果没有第二个参数给出,它采用了当前工作目录。

这将尽量缩短,以给定的长度下。 如果这是不可能的,它只是给它可以给的最短路径。

在算法上来说,这可能是可怕的,但它最终被相当快。 (到快速外壳脚本中的关键是避免子shell和外部命令,特别是在内部循环)。

在设计上,它只有2个或更多字符(“坎*”只是尽可能多的字符“家”)缩短。

它并不完美。 有些情况下也不会尽可能缩短是可能的,就像如果有几个文件,其文件名共享一个前缀(如果foobar1和foobar2存在,foobar3不会缩短。)



Answer 4:

仅供参考,有一个内置的\w在打击“缩短服务” 4+:

PROMPT_DIRTRIM=3

将缩短/var/lib/whatever/foo/bar/baz.../foo/bar/baz



Answer 5:

我做了埃文·克劳的代码一些改进。 现在检查,看看你的路径$ HOME开始,并开始缩短各种〜/不是/小时* / U * /

#!/bin/bash

begin="" # The unshortened beginning of the path.
shortbegin="" # The shortened beginning of the path.
current="" # The section of the path we're currently working on.
end="${2:-$(pwd)}/" # The unmodified rest of the path.

if [[ "$end" =~ "$HOME" ]]; then
    INHOME=1
    end="${end#$HOME}" #strip /home/username from start of string
    begin="$HOME"      #start expansion from the right spot
else
    INHOME=0
fi

end="${end#/}" # Strip the first /
shortenedpath="$end" # The whole path, to check the length.
maxlength="${1:-0}"

shopt -q nullglob && NGV="-s" || NGV="-u" # Store the value for later.
shopt -s nullglob    # Without this, anything that doesn't exist in the filesystem turns into */*/*/...

while [[ "$end" ]] && (( ${#shortenedpath} > maxlength ))
do
  current="${end%%/*}" # everything before the first /
  end="${end#*/}"    # everything after the first /

  shortcur="$current"
  shortcurstar="$current" # No star if we don't shorten it.

  for ((i=${#current}-2; i>=0; i--)); do
    subcurrent="${current:0:i}"
    matching=("$begin/$subcurrent"*) # Array of all files that start with $subcurrent. 
    (( ${#matching[*]} != 1 )) && break # Stop shortening if more than one file matches.
    shortcur="$subcurrent"
    shortcurstar="$subcurrent*"
  done

  #advance
  begin="$begin/$current"
  shortbegin="$shortbegin/$shortcurstar"
  shortenedpath="$shortbegin/$end"
done

shortenedpath="${shortenedpath%/}" # strip trailing /
shortenedpath="${shortenedpath#/}" # strip leading /

if [ $INHOME -eq 1 ]; then
  echo "~/$shortenedpath" #make sure it starts with ~/
else
  echo "/$shortenedpath" # Make sure it starts with /
fi

shopt "$NGV" nullglob # Reset nullglob in case this is being used as a function.

另外,这里有一些功能,我把我的.bashrc文件缩小由shell显示的路径。 我不知道如果这样的编辑$ PWD是完全安全的,因为某些脚本可能依赖于有效的$ PWD字符串,但到目前为止,我还没有与偶尔使用问题。 请注意,我救了上面的脚本“shortdir”,并把它放在我的道路。

function tinypwd(){
    PWD=`shortdir`
}

function hugepwd(){
    PWD=`pwd`
}

编辑2010年10月19日

做别名在bash正确的方法是通过修改$PS1变量; 这是提示的方式解析。 在大多数情况下(的99%的时间)的电流路径是在提示的字符串作为“\ W”。 我们可以使用SED来取代这个shortdir ,就像这样:

#NOTE: trailing space before the closing double-quote (") is a must!!
function tinypwd(){                                                             
    PS1="$(echo $PS1 | sed 's/\\w/\`shortdir\`/g') "
}                                                                               

function hugepwd(){                                                             
    PS1="$(echo $PS1 | sed 's/[`]shortdir[`]/\\w/g') "                            
} 


Answer 6:

这里有埃文的回答另一个旋:

这其中使用加号(+),而不是用于截短的路径的星号(*)。 它取代了〜HOME路径,并留下最后的目录部分完好无损。 如果最终段是超过20个字符,但它缩短到制表completable位,并增加了一个省略号(...)。

#!/bin/bash
# Modified from http://stackoverflow.com/a/1617048/359287
# By Alan Christopher Thomas (http://alanct.com)

__pwd_ps1 ()
{
    begin=""
    homebegin=""
    shortbegin=""
    current=""
    end="${2:-$(pwd)}/" # The unmodified rest of the path.
    end="${end#/}" # Strip the first /
    shortenedpath="$end"

    shopt -q nullglob && NGV="-s" || NGV="-u"
    shopt -s nullglob

    while [[ "$end" ]]
    do
      current="${end%%/*}" # Everything before the first /
      end="${end#*/}" # Everything after the first /

      shortcur="$current"
      for ((i=${#current}-2; i>=0; i--))
      do
        [[ ${#current} -le 20 ]] && [[ -z "$end" ]] && break
        subcurrent="${current:0:i}"
        matching=("$begin/$subcurrent"*) # Array of all files that start with $subcurrent
        (( ${#matching[*]} != 1 )) && break # Stop shortening if more than one file matches
        [[ -z "$end" ]] && shortcur="$subcurrent..." # Add character filler at the end of this string
        [[ -n "$end" ]] && shortcur="$subcurrent+" # Add character filler at the end of this string
      done

      begin="$begin/$current"
      homebegin="$homebegin/$current"
      [[ "$homebegin" =~ ^"$HOME"(/|$) ]] && homebegin="~${homebegin#$HOME}" # Convert HOME to ~
      shortbegin="$shortbegin/$shortcur"
      [[ "$homebegin" == "~" ]] && shortbegin="~" # Use ~ for home
      shortenedpath="$shortbegin/$end"
    done

    shortenedpath="${shortenedpath%/}" # Strip trailing /
    shortenedpath="${shortenedpath#/}" # Strip leading /

    [[ ! "$shortenedpath" =~ ^"~" ]] && printf "/$shortenedpath" # Make sure it starts with /
    [[ "$shortenedpath" =~ ^"~" ]] && printf "$shortenedpath" # Don't use / for home dir

    shopt "$NGV" nullglob # Reset nullglob in case this is being used as a function.
}

点击此处下载脚本,包括在您.bashrc

https://raw.github.com/alanctkc/dotfiles/master/.bash_scripts/pwd-prompt.bash

. ~/.bash_scripts/pwd-prompt.bash

该目录添加到您的PS1是这样的:

export PS1="[other stuff...] \$(__pwd_ps1)\$ "


Answer 7:

下面是一个相对容易的Perl的解决方案。 这是足够短,你可以在PS1直接嵌入它,而不是调用的脚本。 它给人的截断名称的所有字符,而不是取代'。


$ echo '/this/is/a/realy/long/path/id/like/shortened' |
 perl -F/ -ane 'print join( "/", map { $i++ < @F - 2 ?
 substr $_,0,3 : $_ } @F)'
/thi/is/a/rea/lon/pat/id/like/shortened

我没有立即看到一个很好的方式来替换字符,但这里是一个丑陋的方式“”:


echo '/this/is/a/realy/long/path/id/like/shortened' |
 perl -F/ -ane 'print join( "/", map { m/(.)(.*)/;
 $_ = $1 . "." x (length $2 > 2 ? 2 : length $2 ) if $i++ < @F - 2; $_ } @F)'
/t../i./a/r../l../p../i./like/shortened


Answer 8:

试试这个:

PS1='$(pp="$PWD/" q=${pp/#"$HOME/"/} p=${q%?};((${#p}>19))&&echo "${p::9}…${p:(-9)}"||echo "$p") \$'

它改变

~/.vim/bundle/ack.vim/plugin

.vim/bund…im/plugin

transfrom

/usr/share/doc/xorg-x11-font-utils-7.5/

/usr/shar…utils-7.5

而当$PWD一样$HOME ,什么都不显示。

奖励:你可以修改长度的数量,以适应​​你的需要。



文章来源: Bash PWD Shortening
标签: linux bash