1

realpathファイルの実際のパスを取得する簡単な方法を提供するという点で非常に優れていますが、ニーズを満たす方法を見つけることができません (独自の文字列操作を行わないため、専用のユーティリティがおそらく見つけて解決したと思われます)。一言で言えば、返されるパスに含めたい~ので、マシン間で有効になります。

したがって、私が入ってい~/binて入力すると、使用するオプションが である場合に得られる の代わりにrealpath --some-option script.sh返され、オプションを使用しない場合に得られる の代わりに返されます。~/bin/script.shbin/script.sh--relative-base=$HOME/Users/brandon/bin/script.sh

から必要なものを取得する方法はありますかrealpath、または簡単な方法で必要なことを行う他のユーティリティはありますか? それとも、sed私が望むものを得るためにパイプスルーする唯一の本当のオプションですか?

(PS私はOS Xを使用していますが、GNUユーティリティが必要な場合に備えてインストールされています...それがどこrealpathから来たのか、それともOS Xの最近のバージョンにデフォルトでインストールされているのかはわかりません.)

4

2 に答える 2

2

現在のバージョンの OSX (10.11.3) でさえユーティリティが付属していないrealpathため、実際には GNU coreutilsHomebrew パッケージから入手する必要があります。

realpath実際、それ自体で簡単に確認できます。例えば:

$ realpath "$(which realpath)"
/usr/local/Cellar/coreutils/8.24/bin/grealpath

ブジラソの役立つ答えのように、を使用--relative-base="$HOME"して単純に先頭に追加するのが、あなたの場合の最も簡単な解決策です。~/

次の代替案を提案させてください。

  • realpathOSXマシンではその存在を想定できないため、なしで済みます。

    • 代わりに Perl ワンライナーが使用されます (Python もオプションになります)。
  • $HOMEの代わりに を使用します。これは~、パスのベースにする$HOME方が安全な選択だからです (シェルがパスを展開すると仮定します)。

    • $HOMEシェルに渡されるときにパス文字列全体を二重引用符で囲むことができるため、より安全です。埋め込まれたスペースや他のシェルのメタ文字を個別に引用 (エスケープ) することを心配する必要はありません。対照的に、プレフィックス付きのパスでは、パス内の個々の文字~を引用するか、選択的にプレフィックスを引用符なしのままにしておく必要があります( )。~/~/"path/..."
absPath=$(perl -MCwd -le 'print Cwd::abs_path(shift)' "script.sh")
abstractPath="\$HOME${absPath#"$HOME"}"

結果はliteral のようなものになり$HOME/bin/script.sh、シェルによって解釈されると、その時点で現在のユーザー固有のパスに展開されます。

以下に示すように関数を定義するabstractHomePath() bashと、次を使用できます。

abstractPath=$(abstractHomePath "script.sh")  # -> '$HOME/bin/script.sh'

abstractHomePathバッシュ機能:

# Given a relative or absolute path, returns an absolute path in which the path
# prefix that is the current user's home directory is replaced with literal
# '$HOME' so as to yield an abstract path that can later be expanded in a 
# different user's context to get the analogous path. 
#
# If the input path resolves to an absolute path that is *not* prefixed with
# the current user's home diretory path, the absolute path is returned as -is.
#
# Note that any symlinks in the path are resolved to their ultimate targets
# first and that the path is normalized.
#
# Examples:
#    abstractHomePath ~ # -> '$HOME'
#    abstractHomePath /Users/jdoe/Downloads # -> '$HOME/Downloads'
#    abstractHomePath /tmp # -> '/private/tmp' -  symlink resolved, but no $HOME prefix
# Prerequisites:
#    Requires Perl v5+
abstractHomePath() {
  local absPath=$(perl -MCwd -le 'print Cwd::abs_path(shift)' "$1")
  if [[ $absPath == "$HOME"* ]]; then
    printf '%s\n' "\$HOME${absPath#"$HOME"}"
  else
    printf '%s\n' "$absPath"
  fi
}
于 2016-02-27T20:37:34.537 に答える