web-dev-qa-db-ja.com

〜は常に$ HOMEと等しい

これはおそらく以前に尋ねられたと思いますが、Googleでは見つかりませんでした。

与えられた

  • Linuxカーネル
  • $ HOMEを変更する構成はありません
  • bash

~ == $HOME 本当だ?

41
PythonNut

理解しておくべき重要なことは、_~_拡張はシェル(一部のシェルの)の機能であり、使用される場所に関係なくホームディレクトリを意味するのではなく、魔法の特徴ではありません。

コマンドが実行される前にシェルコマンドラインで使用される場合、_$var_が特定の条件下でその値に展開されるように、(コマンドラインの解釈に使用されるアプリケーションであるシェルによって)拡張されます。

この機能は、1970年代後半にCシェルで最初に登場しました(ボーンシェルにはありませんでした。また、その前身であるトンプソンシェルにもありませんでした)は、後にコーンシェルに追加されました(新しいシェルは、 80年代)。最終的にPOSIXによって標準化され、現在fishなどの非POSIXシェルを含むほとんどのシェルで使用できます。

シェルでこのように広く使用されているため、一部の非シェルアプリケーションでも、ホームディレクトリを意味するものとして認識されます。これは、構成ファイルまたはownコマンドライン(muttslrnvim...)内の多くのアプリケーションの場合です。

bashは、具体的には(GNUプロジェクトのシェルであり、多くのLinuxベースのオペレーティングシステムで広く使用されています)、shとして呼び出されると、ほとんど POSIXルール について_~_展開、およびPOSIXで指定されていない領域では、ほとんどがKornシェル(一部はクローン)のように動作します。

_$var_はほとんどの場所で展開されますが(単一引用符内を除く)、_~_の展開は、いくつかの特定の条件でのみ展開されます。

文字列が期待されるコンテキストで、リストコンテキスト内の独自の引数で展開されます。

bashで展開されている場所の例をいくつか示します。

  • _cmd arg ~ other arg_
  • _var=~_
  • _var=x:~:x_(POSIXで必要、PATHMANPATH...などの変数に使用)
  • _for i in ~_
  • _[[ ~ = text ]]_
  • _[[ text = ~ ]]_(_~_の拡張は、AT&T kshではパターンとして採用されていますが、4.0以降ではbashではありません)。
  • _case ~ in ~) ..._
  • _${var#~}_(他の一部のシェルではありません)
  • _cmd foo=~_(shとして呼び出されたときではなく、_=_の左側にあるものが引用符で囲まれていないbash変数名のような形になっている場合のみ)
  • _cmd ~/x_(明らかにPOSIXで必要)
  • _cmd ~:x_(ただし_x:~:x_または_x-~-x_は除く)
  • a[~]=foo; echo "${a[~]} $((a[~]))"(他のシェルにはありません)

次に、拡張されていない例をいくつか示します。

  • _echo "~" '~'_
  • _echo ~@ ~~_(また、_~u_は、ユーザーuのホームディレクトリに展開するためのものです)。
  • _echo @~_
  • _(( HOME == ~ ))_、$(( var + ~ ))
  • extglobの場合:case $var in @(~|other))...(ただし_case $var in ~|other)_は問題ありません)。
  • _./configure --prefix=~_(_--prefix_は有効な変数名ではないため)
  • _cmd "foo"=~_(引用符によりbash内)。
  • shとして呼び出された場合:_export "foo"=~_、_env Java_HOME=~ cmd_...

展開先について:_~_だけがHOME変数の内容に展開されるか、または設定されていない場合は、アカウントデータベースの現在のユーザーのホームディレクトリに展開されます(POSIXはその動作を残すため、拡張機能として未定義)。

4.0より前のバージョンのksh88およびbashでは、チルド展開はリストコンテキストでグロビング(ファイル名生成)を受けていました。

_$ bash -c 'echo "$HOME"'
/home/***stephane***
$ bash -c 'echo ~'
/home/***stephane*** /home/stephane
$ bash -c 'echo "~"'
~
_

通常は問題ありません。

展開されているため、他の形式の展開と同じ警告が適用されることに注意してください。

_cd ~
_

_$HOME_が_-_で始まる、または_.._コンポーネントを含む場合は機能しません。そのため、違いが生じる可能性はほとんどありませんが、厳密に言えば、次のように書く必要があります。

_cd -P -- ~
_

あるいは:

_case ~ in
  (/*) cd -P ~;;
  (*) d=~; cd -P "./$d";;
esac
_

(_$HOME_、_-_...のような_+2_の値をカバーするため)または単に:

_cd
_

cdは引数なしでホームディレクトリに移動します)

他のシェルはより高度な_~_拡張を持っています。たとえば、zshでは、次のようになります。

  • _~4_、_~-_、_~-2_(補完あり)は、ディレクトリスタック内のディレクトリ(cdを以前に配置した場所)を展開するために使用されます。
  • 動的名前付きディレクトリ。独自のメカニズムを定義して、_~something_の展開方法を決定できます。
48

任意のシステムの任意のバージョンのBashでは、はい 。独自の用語としての~は、次のように展開するように定義されています。

$ HOMEの値

そのため、現在のシェルに対する$HOMEの内容と常に同じになります。 userのホームディレクトリの~userなど、他のいくつかのチルダ拡張がありますが、引用符で囲まれていない単一の~は、それ自体で常に"$HOME"に拡張されます。

~$HOME動作が異なる場合があることに注意してください。特に、$HOMEスペース(または他の [〜#〜] ifs [〜#〜] 文字)が含まれている場合、$HOME(引用符なし)は複数の単語に展開されますが、~は常に一つの単語。 ~"$HOME"(引用)と同等に展開されます。

あなたの特定の質問に関して:

[[ $HOME == ~ ]]

[[suppresses ワード分割であるため、常にtrueです。 HOMEパターンマッチング 文字が含まれている場合、[[ ~ == $HOME ]は存在しない可能性がありますが、[[ ~ == "$HOME" ]](つまり、引用符で囲まれた"$HOME")は常にtrueです。単一のブラケット内で使用すると、スペースまたは特殊文字を含むHOMEの値の構文エラーになる可能性があります。賢明なホームディレクトリ構成の場合、~"$HOME"は同じであり、等しいと比較されます。


StéphaneChazelasがコメントで~$HOMEが異なる値を与える場合を指摘しました: unset HOME の場合、~ Bashを使用すると getpwuid を呼び出して、パスワードデータベースから値を読み取ります。このケースは、$HOMEの構成を変更していないという条件によって除外されていますが、ここでは完全を期して説明します。

25
Michael Homer