をめぐる対立を解決するシンボリックリンクシェルスクリプト
質問
された絶対パスまたは相対パス(Unix系システム)思決定をフルパスで対象の後、自らが問題解決に中間symlinks.ボーナスポイントをしても解決~ユーザ名の表記でも同時に行います。
の場合はターゲットがディレクトリにすることは可能ではなchdir()のディレクトリを呼び出getcwd()っていきたいと思っておりますこれからのシェルスクリプトをより書面でCをするヘルパー残念ながら、貝殻る傾向にあるように存在symlinksから、ユーザがこのbashにOS X):
$ ls -ld foo bar
drwxr-xr-x 2 greg greg 68 Aug 11 22:36 bar
lrwxr-xr-x 1 greg greg 3 Aug 11 22:36 foo -> bar
$ cd foo
$ pwd
/Users/greg/tmp/foo
$
だいたい機能を解決()が実行した場合にtmpディレクトリに上記の例では、解決("foo")=="/Users/greg/tmp/バル"。
他のヒント
readlink -f "$path"
編集部注:以上の作品 GNU readlink
や FreeBSD/PC-BSD/OpenBSD readlink
, ものの、 ない OS Xとfig.10.11.
GNU readlink
には、追加の関連などのオプション -m
の解決、シンボリックリンクか否かを究極の目標が存在します。
注意以降、GNU coreutils8.15(2012-01-06)があり realpath プログラム可能性がありますが鈍柔軟にすること。でも、FreeBSD utilす。と機能を相対パスとファイルです。
realpath $path
[Adminのほか、下記からのコメント halloleo —danorton]
Mac OS X(少なくともfig.10.11.x)を使用 readlink
なし -f
オプション:
readlink $path
編集部注:このことは解決symlinks 再帰的に こんに報告し、 究極の ターゲット例えば、シンボリックリンク a
そのポイント b
, し、ポイント c
, こだけ報告書 b
(なることを確認として出力 絶対パス).
以下の perl
コマンドOS Xのギャップを埋めるには readlink -f
機能:
perl -MCwd -le 'print Cwd::abs_path(shift)' "$path"
"pwd-P"という作業のほとんどのディレクトリが、何らかの理由により、あなたの名前の実際の実行ファイルとは思えない役立っています。ここでの私の解
#!/bin/bash
# get the absolute path of the executable
SELF_PATH=$(cd -P -- "$(dirname -- "$0")" && pwd -P) && SELF_PATH=$SELF_PATH/$(basename -- "$0")
# resolve symlinks
while [[ -h $SELF_PATH ]]; do
# 1) cd to directory of the symlink
# 2) cd to the directory of where the symlink points
# 3) get the pwd
# 4) append the basename
DIR=$(dirname -- "$SELF_PATH")
SYM=$(readlink "$SELF_PATH")
SELF_PATH=$(cd "$DIR" && cd "$(dirname -- "$SYM")" && pwd)/$(basename -- "$SYM")
done
お気に入りの一本をする realpath foo
realpath - return the canonicalized absolute pathname realpath expands all symbolic links and resolves references to '/./', '/../' and extra '/' characters in the null terminated string named by path and stores the canonicalized absolute pathname in the buffer of size PATH_MAX named by resolved_path. The resulting path will have no symbolic link, '/./' or '/../' components.
readlink -e [filepath]
もうまい -それを受け付けarbirary経路を解決しsymlinksを返します"リアル"パス で"標準は*nix"そうすべてのシステムで
別の方法:
# Gets the real path of a link, following all links
myreadlink() { [ ! -h "$1" ] && echo "$1" || (local link="$(expr "$(command ls -ld -- "$1")" : '.*-> \(.*\)$')"; cd $(dirname $1); myreadlink "$link" | sed "s|^\([^/].*\)\$|$(dirname $1)/\1|"); }
# Returns the absolute path to a command, maybe in $PATH (which) or not. If not found, returns the same
whereis() { echo $1 | sed "s|^\([^/].*/.*\)|$(pwd)/\1|;s|^\([^/]*\)$|$(which -- $1)|;s|^$|$1|"; }
# Returns the realpath of a called command.
whereis_realpath() { local SCRIPT_PATH=$(whereis $1); myreadlink ${SCRIPT_PATH} | sed "s|^\([^/].*\)\$|$(dirname ${SCRIPT_PATH})/\1|"; }
けが指定されたソリューションであることを知りながreadlinkはほとんどのシステムが異なる引数をこの作品にもなったのかはOSXとすることが目的です。はわかりませんBSDシステム。(粉を山にして真ん中を条件にする必要 [[ $OSTYPE != darwin* ]]
除外 -f
からOSXのみです。
#!/bin/bash
MY_DIR=$( cd $(dirname $(readlink `[[ $OSTYPE == linux* ]] && echo "-f"` $0)) ; pwd -P)
echo "$MY_DIR"
注意:これは、固体測は、既製のソリューションは、人々の 長い そのも理由です。
以下では 完全にPOSIXに準拠したスクリプト機能 そのため、 クロスプラットフォーム (作macOSさせるものとなり、 readlink
まだ対応しておりません -f
としての10.12(シエラ))-のみを使用して POSIXシェルの言語の特徴 みPOSIXに準拠した体に発信します。
です 携帯の実施GNUの readlink -e
の強化版 readlink -f
).
ができ 走る スクリプト と sh
または ソースの 機能 に bash
, ksh
, は、 zsh
:
例えば、内部スクリプトを使用でき法については以下を参考にして取得し、走行のスクリプトの真のディレクトリの起源は、symlinks解決:
trueScriptDir=$(dirname -- "$(rreadlink "$0")")
rreadlink
スクリプト機能の定義
このコードに対し感謝の気持ちから この答え.
私も作成しました bash
ベ単体版 こちらの, は、インストールすることができ付
npm install rreadlink -g
, ばNode.js れます。
#!/bin/sh
# SYNOPSIS
# rreadlink <fileOrDirPath>
# DESCRIPTION
# Resolves <fileOrDirPath> to its ultimate target, if it is a symlink, and
# prints its canonical path. If it is not a symlink, its own canonical path
# is printed.
# A broken symlink causes an error that reports the non-existent target.
# LIMITATIONS
# - Won't work with filenames with embedded newlines or filenames containing
# the string ' -> '.
# COMPATIBILITY
# This is a fully POSIX-compliant implementation of what GNU readlink's
# -e option does.
# EXAMPLE
# In a shell script, use the following to get that script's true directory of origin:
# trueScriptDir=$(dirname -- "$(rreadlink "$0")")
rreadlink() ( # Execute the function in a *subshell* to localize variables and the effect of `cd`.
target=$1 fname= targetDir= CDPATH=
# Try to make the execution environment as predictable as possible:
# All commands below are invoked via `command`, so we must make sure that
# `command` itself is not redefined as an alias or shell function.
# (Note that command is too inconsistent across shells, so we don't use it.)
# `command` is a *builtin* in bash, dash, ksh, zsh, and some platforms do not
# even have an external utility version of it (e.g, Ubuntu).
# `command` bypasses aliases and shell functions and also finds builtins
# in bash, dash, and ksh. In zsh, option POSIX_BUILTINS must be turned on for
# that to happen.
{ \unalias command; \unset -f command; } >/dev/null 2>&1
[ -n "$ZSH_VERSION" ] && options[POSIX_BUILTINS]=on # make zsh find *builtins* with `command` too.
while :; do # Resolve potential symlinks until the ultimate target is found.
[ -L "$target" ] || [ -e "$target" ] || { command printf '%s\n' "ERROR: '$target' does not exist." >&2; return 1; }
command cd "$(command dirname -- "$target")" # Change to target dir; necessary for correct resolution of target path.
fname=$(command basename -- "$target") # Extract filename.
[ "$fname" = '/' ] && fname='' # !! curiously, `basename /` returns '/'
if [ -L "$fname" ]; then
# Extract [next] target path, which may be defined
# *relative* to the symlink's own directory.
# Note: We parse `ls -l` output to find the symlink target
# which is the only POSIX-compliant, albeit somewhat fragile, way.
target=$(command ls -l "$fname")
target=${target#* -> }
continue # Resolve [next] symlink target.
fi
break # Ultimate target reached.
done
targetDir=$(command pwd -P) # Get canonical dir. path
# Output the ultimate target's canonical path.
# Note that we manually resolve paths ending in /. and /.. to make sure we have a normalized path.
if [ "$fname" = '.' ]; then
command printf '%s\n' "${targetDir%/}"
elif [ "$fname" = '..' ]; then
# Caveat: something like /var/.. will resolve to /private (assuming /var@ -> /private/var), i.e. the '..' is applied
# AFTER canonicalization.
command printf '%s\n' "$(command dirname -- "${targetDir}")"
else
command printf '%s\n' "${targetDir%/}/$fname"
fi
)
rreadlink "$@"
接線安全保障:
トゥルーリ, 参照機能を組み込み command
な影のエシェル機能は、同じ名前の問、コメント:
どの場合
unalias
またはunset
や[
として設定されているエイリアスはシェルの性能におい
の背後にある動機 rreadlink
を確保 command
その本来の意味を理解することはご使用いただけバイパス(良性) 利便性 エイリアス機能によく使われる標準コマンド区分コマンドインタラクティブ-貝などの再定義 ls
を好みます。
と思うので安全とは言いませんが取り組むことで、信頼できない悪意のある環境を気にし unalias
または unset
または、 while
, do
,...-再定義さは一つの関心事となっています。
はありま 何か この機能に頼らざるを得ないにして、その本来の意味を理解することと行動が周りとのこと。
ることが含貝殻を再定義のbuiltinsとでも言語キーワード 本質的に したセキュリティリスク(書被害妄想コードは一般).
題への対応具体的には:
この機能に依存して unalias
や unset
有元の意味があります。して再定義してい シェル機能 に伴って変化するシリコン構造体の挙動する問題再定義として 別名 は
というわけではありませんの懸念が 引用 (一部)をコマンドの名前(例、 \unalias
)fpga別名になります。
しかし、引用が ない オプションのためのシェル キーワード (while
, for
, if
, do
,...)がシェルのキーワードだが優先するものとしますシェル 機能, は、 bash
や zsh
エイリアスの最も高い優先順位、防シェル-キーワードredefinitionsお店 unalias
その名は 非インタラクティブ bash
貝殻などのスクリプト)のエイリアスが ない 拡大によるデフォルトのみの場合 shopt -s expand_aliases
明示的に呼びするものではありません。
保 unalias
-として組み込み-その本来の意味を理解することより、すきまが大きくな \unset
で初ている必要があり unset
その本来の意味を理解すること:
unset
はシェル 組み込み, で確なものとするために呼び出されているのではないもの"と再定義 機能.ることができますしながら、バイパスエイリアスの形式と引用はできませんバイパスシェル機能の形成-獲22.
このような頼れるパートナーです unset
してその本来の意味を理解することになった"と投票してい伝えが保証はできませんの方におけるすべて悪意のあるredefinitions.
共通のシェルスクリプトが見つ"ホームディレクトリであっても呼び出されたとしてシンボリックリンク.スクリプトに従いて"において位置から$0になります。
cat `mvn`
自分のシステムの版画のスクリプトに以下を含むべき作品で作られています。
if [ -z "$M2_HOME" ] ; then
## resolve links - $0 may be a link to maven's home
PRG="$0"
# need this for relative symlinks
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG="`dirname "$PRG"`/$link"
fi
done
saveddir=`pwd`
M2_HOME=`dirname "$PRG"`/..
# make it fully qualified
M2_HOME=`cd "$M2_HOME" && pwd`
function realpath {
local r=$1; local t=$(readlink $r)
while [ $t ]; do
r=$(cd $(dirname $r) && cd $(dirname $t) && pwd -P)/$(basename $t)
t=$(readlink $r)
done
echo $r
}
#example usage
SCRIPT_PARENT_DIR=$(dirname $(realpath "$0"))/..
してみてください:
cd $(dirname $([ -L $0 ] && readlink -f $0 || echo $0))
以来、思いこの近くに、今回も純bash携帯バージョンが使用OSX、linux、先を行ったとの論文も含まれてい:
生活版の生活はこちら
https://github.com/keen99/shell-functions/tree/master/resolve_path
しかし、では、現在のバージョン(もうとして指を切りそうになったの試験ようですが、私はオフィードバック!)
のような困難はそれを動作させるために平bourneシェルコート(sh)がいう思$FUNCNAMEます。:)
#!/bin/bash
resolve_path() {
#I'm bash only, please!
# usage: resolve_path <a file or directory>
# follows symlinks and relative paths, returns a full real path
#
local owd="$PWD"
#echo "$FUNCNAME for $1" >&2
local opath="$1"
local npath=""
local obase=$(basename "$opath")
local odir=$(dirname "$opath")
if [[ -L "$opath" ]]
then
#it's a link.
#file or directory, we want to cd into it's dir
cd $odir
#then extract where the link points.
npath=$(readlink "$obase")
#have to -L BEFORE we -f, because -f includes -L :(
if [[ -L $npath ]]
then
#the link points to another symlink, so go follow that.
resolve_path "$npath"
#and finish out early, we're done.
return $?
#done
elif [[ -f $npath ]]
#the link points to a file.
then
#get the dir for the new file
nbase=$(basename $npath)
npath=$(dirname $npath)
cd "$npath"
ndir=$(pwd -P)
retval=0
#done
elif [[ -d $npath ]]
then
#the link points to a directory.
cd "$npath"
ndir=$(pwd -P)
retval=0
#done
else
echo "$FUNCNAME: ERROR: unknown condition inside link!!" >&2
echo "opath [[ $opath ]]" >&2
echo "npath [[ $npath ]]" >&2
return 1
fi
else
if ! [[ -e "$opath" ]]
then
echo "$FUNCNAME: $opath: No such file or directory" >&2
return 1
#and break early
elif [[ -d "$opath" ]]
then
cd "$opath"
ndir=$(pwd -P)
retval=0
#done
elif [[ -f "$opath" ]]
then
cd $odir
ndir=$(pwd -P)
nbase=$(basename "$opath")
retval=0
#done
else
echo "$FUNCNAME: ERROR: unknown condition outside link!!" >&2
echo "opath [[ $opath ]]" >&2
return 1
fi
fi
#now assemble our output
echo -n "$ndir"
if [[ "x${nbase:=}" != "x" ]]
then
echo "/$nbase"
else
echo
fi
#now return to where we were
cd "$owd"
return $retval
}
ここでの典型例は、brew:
%% ls -l `which mvn`
lrwxr-xr-x 1 draistrick 502 29 Dec 17 10:50 /usr/local/bin/mvn@ -> ../Cellar/maven/3.2.3/bin/mvn
この機能を利用でのリアルタイムパス:
%% cat test.sh
#!/bin/bash
. resolve_path.inc
echo
echo "relative symlinked path:"
which mvn
echo
echo "and the real path:"
resolve_path `which mvn`
%% test.sh
relative symlinked path:
/usr/local/bin/mvn
and the real path:
/usr/local/Cellar/maven/3.2.3/libexec/bin/mvn
仕事のMac不適合が浮かび上がった
echo `php -r "echo realpath('foo');"`
なの観光スポットを表示一部の観光クロスOS
こちらはどのように取り組むべきかを実際のパスにファイルMacOS/Unixを使用するインラインPerlスクリプト:
FILE=$(perl -e "use Cwd qw(abs_path); print abs_path('$0')")
同様に、ディレクトリのsymlinkedファイル:
DIR=$(perl -e "use Cwd qw(abs_path); use File::Basename; print dirname(abs_path('$0'))")
はpathディレクトリ、またはあなファイルとは何ですか?の場合はディレクトリでは、シンプルです:
(cd "$DIR"; pwd -P)
ただし、このファイル、これは動作しません:
DIR=$(cd $(dirname "$FILE"); pwd -P); echo "${DIR}/$(readlink "$FILE")"
でのシンボリックリンクが解決への相対のフルパス。
上のスクリプトだ実際のパスのように、そしても参考に設定、またはその他のスクリプトと一緒にインストールされ、その結果が、先ほど任天堂さん:
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
SOURCE="$(readlink "$SOURCE")"
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
done
きセット SOURCE
載のファイルパスになります。基本的には、どの経路であるシンボリックリンクで解決するシンボリックリンク.フレキシビリティの最終ラインのループを実行します。場合には、決議されたシンボリックリンクは絶対で使用することとして SOURCE
.ただし、相対での誤動作防止) DIR
で、分解され、実際の場所は簡単なトリック初めて説明します。
ではないかとも思いましたがtrueの決定版"を解決するうえで、シンボリックリンク"かどうかはディレクトリ外のディレクトリを使用Bash:
function readlinks {(
set -o errexit -o nounset
declare n=0 limit=1024 link="$1"
# If it's a directory, just skip all this.
if cd "$link" 2>/dev/null
then
pwd -P "$link"
return 0
fi
# Resolve until we are out of links (or recurse too deep).
while [[ -L $link ]] && [[ $n -lt $limit ]]
do
cd "$(dirname -- "$link")"
n=$((n + 1))
link="$(readlink -- "${link##*/}")"
done
cd "$(dirname -- "$link")"
if [[ $n -ge $limit ]]
then
echo "Recursion limit ($limit) exceeded." >&2
return 2
fi
printf '%s/%s\n' "$(pwd -P)" "${link##*/}"
)}
すべての cd
や set
ものから独立したサブシェルで.
ここっていることだと思っているクロスプラットフォーム(Linux、macOS少なくとも)溶液に答え取り組んでいるのは世界的に見ても私にとってます。
crosspath()
{
local ref="$1"
if [ -x "$(which realpath)" ]; then
path="$(realpath "$ref")"
else
path="$(readlink -f "$ref" 2> /dev/null)"
if [ $? -gt 0 ]; then
if [ -x "$(which readlink)" ]; then
if [ ! -z "$(readlink "$ref")" ]; then
ref="$(readlink "$ref")"
fi
else
echo "realpath and readlink not available. The following may not be the final path." 1>&2
fi
if [ -d "$ref" ]; then
path="$(cd "$ref"; pwd -P)"
else
path="$(cd $(dirname "$ref"); pwd -P)/$(basename "$ref")"
fi
fi
fi
echo "$path"
}
こちらはmacOS(?) ます。が適しての質問です。
mac_realpath()
{
local ref="$1"
if [[ ! -z "$(readlink "$ref")" ]]; then
ref="$(readlink "$1")"
fi
if [[ -d "$ref" ]]; then
echo "$(cd "$ref"; pwd -P)"
else
echo "$(cd $(dirname "$ref"); pwd -P)/$(basename "$ref")"
fi
}