Bashプロンプトでディレクトリ名を引用する

Bashプロンプトでディレクトリ名を引用する

プロンプトで現在のディレクトリを参照したいと思います。

たとえば、これを行うと:

mkdir $'new\nline'; cd $'new\nline'

$'new\nline'プロンプトを印刷する代わりに、リテラル改行文字を表示したいと思います。

\次からバックスラッシュ()を印刷しようとすると、面白い動作が表示されますbash 5.0.9

p='\\n'       && echo -E "${p@P}"  # 2 slashes; output = '\n'
p='\\\\n'     && echo -E "${p@P}"  # 4 slashes; output = '\n'
p='\\\\\\n'   && echo -E "${p@P}"  # 6 slashes; output = '\\n'
p='\\\\\\\\n' && echo -E "${p@P}"  # 8 slashes; output = '\\n'

メモ:${parameter@P}parameterヒントのように値を拡張した結果である文字列です。

出力が(2と4)と(6と8)スラッシュと同じ理由は何ですか?

これらの混乱を考慮すると、次のようになります。

mkdir '\\n' && cd '\\n'

\\nプロンプトに:\\\\nまたはで表示されるようにプログラムで文字列に変換する方法$'\\\\n'と、リテラル改行状況を処理する方法はわかりません。


プロンプトで参照されるディレクトリ名を取得するにはどうすればよいですか?例:

  • ~サブディレクトリを表示し、その$HOME前に表示~/
  • 必要に応じて他のルートを脱出してください
  • 表示文字列のコピー - 貼り付けは、現在のディレクトリを参照する有効なシェルトークンです。

たとえば、"$HOME/dir with spaces"次のようになります。

  • ~/dir\ with\ spaces
  • ~/$'dir with spaces'
  • ~/'dir with spaces'

答え1

Bashは、プロンプトにおよびを含む場合にのみ\wプロンプトにcd $'/tmp/new\nline'表示されます。/tmp/newlineリテラルの改行を印刷しないようですが、明示的な出力形式ではありません。

${var@P}\uユーザー名、\hホスト名、\w作業ディレクトリなどの項目に対してプロンプトエスケープを拡張するように設計されています。逆に、${var@Q}どのような引用結果がより役に立ちますか?

settings PS1='${PWD@Q}\$ '、プロンプトが表示されます:$'/tmp/new\nline'$または'/tmp'$パスが良い場合。別のオプションは、PS1='$(printf "%q" "$PWD")\$ '場合によっては異なる引用符を提供することです。たとえば、「良い」パスの場合は引用符を省略します/tmp$


ホームディレクトリをチルダとして表示するには、1つのオプションは手動で置き換えることです。

set_ppath() {
    printf -v ppath "%q" "$PWD"
    ppath="${ppath/$HOME/"~"}";
}
PROMPT_COMMAND=set_ppath
PS1='$ppath\$ '

まだ言及しているみんなただし、その一部を参照する必要がある場合はパスです。この問題を解決するには、少しずつこの道をたどる必要があると思います。


ところで、バックスラッシュがなぜこんなに折れているのかわかりません${var@P}

答え2

ilkkachuの答えに基づいて、次のことを思い出しました。

PROMPT_COMMAND=_prompt_bash_set

_prompt_bash_set() {
  # Working directory
  local prefix=''  # Used to contain '~' if $PWD directory is under $HOME
  local dir=$PWD

  # Replace leading $HOME with ~ if at beginning of string
  case "$PWD"/ in # Extra slash at end prevents substring match
    "$HOME"/)  # $PWD == $HOME itself
      prefix=\~  # no trailing /
      dir='' ;;
    "$HOME"/?*)  # $PWD is a subdir of $HOME
      prefix=\~/  # Add trailing / so that possibly quoted string goes after ~/ for path validity
      dir=${PWD#$HOME/} ;;   # Remove $HOME and / as this is now in $prefix
  esac

  if [[ $PWD != $HOME ]]; then  # $PWD != $HOME
    # Avoid ${PWD@Q} as it produced a literal \n inside $''
    printf -v dir '%q' "$dir"  # Quote directory minus $HOME

    # Replace a single slash with 4!?! slashes
    # https://unix.stackexchange.com/q/543473/143394
    dir=${dir//\\/\\\\\\\\}

    # Prevent command and variable substitution:
    dir=${dir//\`/\\\`}  # escape ` as \`
    dir=${dir//\$/\\\$}  # escape $ as \$
  fi

  PS1='\u@\h:'$dir'\$ '
}

$PS1これには、変数を介さずにリテラルテキストとして参照されるディレクトリが含まれます。

続けることができるという利点があります。ディレクトリのカラースラッシュ私の目は分析する方が簡単だと思います。

関連情報