Bashプロンプト:ディレクトリパスのイニシャルを取得する方法


4

私は通常bashプロンプト(PS1='\u@\h:\W$ ')に現在のディレクトリの名前だけを持っているので、私がいる場合は次のよう~/projects/superapp/src/になります:

hamish@host:src$ 

ただし、フルパスを使用せずにフルパスを表示したいのですが。私は人々が持っているスクリーンショットを見てきました

hamish@host:~/p/s/src$ 

上記の例のディレクトリにある場合。それでは、PS1のどのような価値がそれをもたらすでしょうか?それとも失敗した場合、それを作成するにはどのスクリプトが必要.bashrcですか?


2
これは素晴らしい質問ですが、Stack Overflowの質問(既に回答済み)とまったく同じです:stackoverflow.com/questions/1616678/bash-pwd-shortening
Telemachus

3
似ていますが、実際には完全な複製ではありません。しかし、それを見ると、私が望んでいることを正確に行う方法を簡単に見ることができません。これは固定長ではなく、イニシャルにすぎません。成功したら、答えをここに投稿するかもしれません。
ハミッシュダウナー

けっこうだ。そのスレッドに基づいて、以下の回答を投稿しました。
テレマコス

1
また、これは複製です。
デニスウィリアムソン

@Telemachus-別のサイトのソリューションを参照するのは良いことですが、両方のサイトにトピックがある場合、両方のサイトに質問が存在できない理由はありません。この質問はスーパーユーザーに関するトピックであり、ここで回答することができます。
グヌーピ

回答:


2

OK

  1. 最初に、上記のコメントでリンクしたSOの質問に対するWilliam Pursellの回答を少し調整して、関数を作成します。
  2. 次に、それを\$(function_name)適切な場所にある$ PS1に入れます。

例として:

short_pwd() {
    cwd=$(pwd | perl -F/ -ane 'print join( "/", map { $i++ < @F - 1 ?  substr $_,0,1 : $_ } @F)')
    echo -n $cwd
}
# later in your .bashrc
PS1="\u \$(short_pwd) \$ "

私よりもBashスクリプトの熟練者が関数をクリーンアップする方法を提案できることを期待していますが、これにより、プロンプトで別のコマンド(またはBash関数)の出力を使用する方法についてのアイデアが得られるはずです。こちらもご覧くださいhttp : //www.linux.org/docs/ldp/howto/Bash-Prompt-HOWTO/x279.html

あなたのコメントに基づいて、私はもう一度見て、私のソリューションを二重引用符で囲む必要があることに気付きました。このような関数を単一引用符で囲むと、まったく機能しなくなります。


私はperlを知らないので一般的な解決策を判断することはできませんが、私の解決策のように編集する必要がありますPROMPT_COMMAND。そうしないPS1と、bashを起動したときに設定され、ディレクトリを変更しても変更されません。
ハミッシュダウナー

@Hamishいいえ、それは間違っています。これはあなたに応じて変わりますcd。今使っています。(そして、それはPerlのことではない、それはあなたが経由して機能してそこに動的な情報を持つことができる方法PS1作品に関係している。。 \$(function)
テレマコス

@Hamishしかし、あなたは私が最初に書いたように単一ではなく二重引用符が必要であることを確認するのを助けてくれました。ここでテストしているプロンプトには、色のエスケープが含まれており、より複雑であり、単一引用符を使用して誤って簡略化しました。ごめんなさい。
テレマコス

面白い、私は明らかに...バッシュについてもう少し学ぶ必要がああ
ハミッシュダウナー

3

私はmeowsqueakのアプローチが好きです。しかし、長いディレクトリ名を1文字に短縮するパスが必要でした。

me@comp:~ $ cd my/path/haslongnames/
me@comp:~my/p/h $

これは、meowsqueakのソリューションに基づいています。いくつかの改善/より多くの機能に耐えることができますが、sedを起動せずに基本的な問題を解決します。

これは、たとえば〜/ bin / ps1などの実行可能ファイルにあります。

# set this to whatever you want:
MAX_PWD_LENGTH=30
function shorten_pwd
{
    # This function ensures that the PWD string does not exceed $MAX_PWD_LENGTH characters
    PWD=$(pwd)

    # determine part of path within HOME, or entire path if not in HOME
    RESIDUAL=${PWD#$HOME}

    # compare RESIDUAL with PWD to determine whether we are in HOME or not
    if [ X"$RESIDUAL" != X"$PWD" ]
    then
        PREFIX="~"
    fi

    # check if residual path needs truncating to keep total length below MAX_PWD_LENGTH
    NORMAL=${PREFIX}${RESIDUAL}
    if [ ${#NORMAL} -ge $(($MAX_PWD_LENGTH)) ]
    then
        newPWD=${PREFIX}
        OIFS=$IFS
        IFS='/'
        bits=$RESIDUAL
        for x in $bits
        do
            if [ ${#x} -ge 3 ]
            then
                NEXT="/${x:0:1}"
            else
                NEXT="$x"
            fi
            newPWD="$newPWD$NEXT"
        done

        IFS=$OIFS
    else
        newPWD=${PREFIX}${RESIDUAL}
    fi

    # return to caller
    echo $newPWD
}
export PS1="\u@\h:$(shorten_pwd) $ "

私の.bash_profileには

PROMPT_COMMAND="source $HOME/bin/ps1"

関数が行で文句を言わない方法を説明してもらえますか:RESIDUAL=${PWD#$HOME} シンタックスハイ
ライターでさえ

正直@stagl、このプロンプトを使用してから何年も経ちました。これが機能する理由についてはあまり覚えていません。:/
レフ

1
補遺。他のsoemthingを研究しているときにこれを見つけました。gnu.org/software/bash/manual/html_node/… 「単語は展開され、ファイル名展開と同様にパターンを生成します(ファイル名展開を参照)。パターンがパラメータの展開値の先頭に一致する場合、展開は、最短の一致パターンを持つパラメーターの展開値です(「#」の場合)」
leff

3
PROMPT_DIRTRIM=3

\ wを現在の作業ディレクトリパスの最大3つの末尾要素に展開し、先行するものがある場合は「...」に置き換えます。


2

数年前に書いた別のスクリプトに基づいて、最近これを書き直しました。これは、コストのかかるフォークを避けるために、可能な限りbash内で実行するように最適化されています。これは、awk / sedを使用していた古い関数よりもほぼ8倍高速でした。

良い結果が得られます。プロンプトのpwd部分をMAX_PWD_LENGTH文字以下に保持します。また、$ HOMEのサブディレクトリにいる場合、これも明確になります。

例:

pc770-ubu:~ $ cd ~/a/b/c
pc770-ubu:~/a/b/c $ cd d/e/f
pc770-ubu:~/a/b/c/d/e/f $ cd g
pc770-ubu:~/a/b/c/d/e/f/g $ cd h
pc770-ubu:~/a/b/c/d/e/f/g/h $ cd i
pc770-ubu:~/a/b/c/d/e/f/g/h/i $ cd j
pc770-ubu:~/a/b/c/d/e/f/g/h/i/j $ cd k
pc770-ubu:~/a/b/c/d/e/f/g/h/i/j/k $ cd l
pc770-ubu:~../c/d/e/f/g/h/i/j/k/l $ cd m
pc770-ubu:~../d/e/f/g/h/i/j/k/l/m $ cd n
pc770-ubu:~../e/f/g/h/i/j/k/l/m/n $ cd o
pc770-ubu:~../f/g/h/i/j/k/l/m/n/o $ cd /tmp/a/b/c/d/e/f
pc770-ubu:/tmp/a/b/c/d/e/f $ cd g
pc770-ubu:/tmp/a/b/c/d/e/f/g $ cd h
pc770-ubu:/tmp/a/b/c/d/e/f/g/h $ cd i
pc770-ubu:/tmp/a/b/c/d/e/f/g/h/i $ cd j
pc770-ubu:/../a/b/c/d/e/f/g/h/i/j $ cd k
pc770-ubu:/../b/c/d/e/f/g/h/i/j/k $ cd l
pc770-ubu:/../c/d/e/f/g/h/i/j/k/l $ cd m
pc770-ubu:/../d/e/f/g/h/i/j/k/l/m $ cd
pc770-ubu:~ $ 

bash関数(PS1変数を作成するときにこれを呼び出します):

# set this to whatever you want:
MAX_PWD_LENGTH=20

function shorten_pwd
{
    # This function ensures that the PWD string does not exceed $MAX_PWD_LENGTH characters
    PWD=$(pwd)

    # if truncated, replace truncated part with this string:
    REPLACE="/.."

    # determine part of path within HOME, or entire path if not in HOME
    RESIDUAL=${PWD#$HOME}

    # compare RESIDUAL with PWD to determine whether we are in HOME or not
    if [ X"$RESIDUAL" != X"$PWD" ]
    then
        PREFIX="~"
    fi

    # check if residual path needs truncating to keep total length below MAX_PWD_LENGTH
    # compensate for replacement string.
    TRUNC_LENGTH=$(($MAX_PWD_LENGTH - ${#PREFIX} - ${#REPLACE} - 1))
    NORMAL=${PREFIX}${RESIDUAL}
    if [ ${#NORMAL} -ge $(($MAX_PWD_LENGTH)) ]
    then
        newPWD=${PREFIX}${REPLACE}${RESIDUAL:((${#RESIDUAL} - $TRUNC_LENGTH)):$TRUNC_LENGTH}
    else
        newPWD=${PREFIX}${RESIDUAL}
    fi

    # return to caller
    echo $newPWD
}

編集:絶対文字列長のバグを修正


1

にこれを追加して(そして、好きなように編集してください).bashrc

PS1='\u@\h:`pwd | sed -e "s/\/\(.\)[^\/]\+/\/\1/g"`\$ '

私はそれを試してみましたが、残念なことに、PS1bashを起動すると、一度だけ値が設定され、その後は更新されません。したがって、ディレクトリを変更してもプロンプトは変更されません。この間違いを犯してからプレイしていたので、頭を悩まして解決しなければなりませんでした。この使用方法についての私の(編集された)答えを参照してくださいPROMPT_COMMAND
ハミッシュダウナー

いいえ、それは私のために働きます、それは毎回変わります。
cYrus

そして、以下echo $PS1を与えます:\ u @ \ h: 'pwd | sed -e "s / \ /(。)[^ \ /] \ + / \ / \ 1 / g" '\ $なので、変数にハードコーディングされません(このマークアップをオーバーライドする方法がわかりません。 'を `)に置き換えます。
cYrus

わかった 説明していただきありがとうございます。
ハミッシュダウナー

1

その間はもう少しグーグルで調べましたが、いくつかの検索用語を調べた後、私はこの記事に出会って、魚の殻が私が望んでいることを行い、それを行う方法を提供しました。ユーザーとホストも表示されるように変更し、合理的に簡潔にしました。

# abbreviate the dir path
PROMPT_COMMAND='CurDir=`pwd|sed -e "s!$HOME!~!"|sed -re "s!([^/])[^/]+/!\1/!g"`'
PS1="\u@\h:\$CurDir \$ "

基本的に、プロンプトが表示されようとするたびに、で使用される短縮ディレクトリパスPROMPT_COMMANDが設定$CurDirされ$PS1ます。PROMPT_COMMANDが他の場所に設定されている場合は、上記のコマンドをその前に;。を付けて追加する必要があることに注意してください。したがって、xtermのタイトルを設定する一般的な例では、次のようになります。

PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD/$HOME/~}\007"; CurDir=`pwd|sed -e "s!$HOME!~!"|sed -re "s!([^/])[^/]+/!\1/!g"`'

パスを短縮する他のいくつかの可能な方法を見つけることができます。


1

perl要件のない@Telemachus short_pwd()の別のバージョン。

short_pwd() {
cwd=$(pwd)

if [ $cwd == $HOME ]; then echo -n "~"; return; fi 
if [ $cwd == "/" ]; then echo -n "/"; fi 

for l in $(echo $cwd | tr "/" "\n"); do 
    echo -n "/"
    echo -n ${l:0:1}
done
echo -n ${l:1}
}

0

これを試して:

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

変身する

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

.vim/bundim/plugin

変換する

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

/usr/sharutils-7.5

$PWD同じ場合$HOME、何も表示されません。

ボーナス:必要に応じて長さの数を変更できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.