私のスクリプトへの引数として、いくつかのファイルパスがあります。もちろん、それらは相対的(または〜を含む)にすることができます。しかし、私が書いた関数には、絶対的なパスが必要ですが、シンボリックリンクは解決されていません。
このための機能はありますか?
私のスクリプトへの引数として、いくつかのファイルパスがあります。もちろん、それらは相対的(または〜を含む)にすることができます。しかし、私が書いた関数には、絶対的なパスが必要ですが、シンボリックリンクは解決されていません。
このための機能はありますか?
readlink
シンボリックリンクを解決します。OPはそれを望んでいません。
echo $(cd some_directory && pwd)
、シンボリックリンクを解決しない、some_directoryが存在しない場合は失敗します。作業ディレクトリは影響を受けません。または変数に割り当てますMY_PATH=$(cd some_directory && pwd)
。
回答:
MY_PATH=$(readlink -f $YOUR_ARG)
"./"
およびのような相対パスを解決します"../"
これも考慮してください(ソース):
#!/bin/bash
dir_resolve()
{
cd "$1" 2>/dev/null || return $? # cd to desired directory; if fail, quell any error messages but return exit status
echo "`pwd -P`" # output full, link-resolved path
}
# sample usage
if abs_path="`dir_resolve \"$1\"`"
then
echo "$1 resolves to $abs_path"
echo pwd: `pwd` # function forks subshell, so working directory outside function is not affected
else
echo "Could not reach $1"
fi
man pwd
:「-P物理的な現在の作業ディレクトリを表示します(すべてのシンボリックリンクが解決されました)」、-P
function abspath {
if [[ -d "$1" ]]
then
pushd "$1" >/dev/null
pwd
popd >/dev/null
elif [[ -e "$1" ]]
then
pushd "$(dirname "$1")" >/dev/null
echo "$(pwd)/$(basename "$1")"
popd >/dev/null
else
echo "$1" does not exist! >&2
return 127
fi
}
pushd
/を使用popd
して、pwd
有用な状態になります。
DIRSTACK
ます。これは実際にはbashのローカルの問題であり、他には何もありません。いい解決策!
sh
互換性を目指す場合は、pushd; cd <dir>; <cmd>; popd
に置き換えることができます(cd <dir>; <cmd>)
。
シンプルなワンライナー:
function abs_path {
(cd "$(dirname '$1')" &>/dev/null && printf "%s/%s" "$PWD" "${1##*/}")
}
使用法:
function do_something {
local file=$(abs_path $1)
printf "Absolute path to %s: %s\n" "$1" "$file"
}
do_something $HOME/path/to/some\ where
パスが存在するかどうかを完全に気にしないようにする方法をまだ模索しています(ファイルの作成時にも使用できます)。
cd -
、その後、それをリセットするには?
${1##*/}
てbasename
、別の変数に入れず、しかしを、スペースでパスが正しく動作しません。
$PWD
:そしてそれを通してそれを実行し、それは非常にうまく動作するはずgithub.com/andsens/homeshick/blob/...は
OSXでは使用できます
stat -f "%N" YOUR_PATH
Linuxでは、realpath
実行可能ファイルがあるかもしれません。そうでない場合は、以下が機能する可能性があります(リンクだけでなく)。
readlink -c YOUR_PATH
stat -f "%N" PATH
私が与えたのとまったく同じ道を私に与えます。
自己編集、私はちょうどOPが解決されたシンボリックリンクを探していないと言ったことに気づきました:
「しかし、私が書いた関数には、絶対的なパスが必要ですが、シンボリックリンクは解決されていません。」
結局、これは彼の質問にはそれほど適切ではないと思います。:)
私は何年にもわたってこれに何度も遭遇し、今回はOSXとLinuxで使用できる純粋なbashポータブルバージョンが必要だったので、先に進んで次のように書きました。
生きているバージョンはここに住んでいます:
https://github.com/keen99/shell-functions/tree/master/resolve_path
しかし、SOのために、これが現在のバージョンです(十分にテストされていると思いますが、フィードバックを受け付けています!)
プレーンボーンシェル(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
この関数を使用すると、-real-パスが返されます。
%% 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
OSがサポートしている場合は、次を使用します。
realpath "./some/dir"
そしてそれを変数で使用する:
some_path="$(realpath "./some/dir")"
それはあなたの道を拡大します。UbuntuとCentOSでテストされていますが、ご利用いただけない場合があります。readlinkを推奨する人もいますが、readlinkのドキュメントには次のように書かれています。
realpath(1)は、正規化機能に使用する推奨コマンドであることに注意してください。
なぜ変数を引用するのか不思議に思う人のために、パスのスペースを保持することです。行うrealpath some path
ように、2つの異なるパス結果が得られます。しかし、realpath "some path"
1つを返します。引用されたパラメータftw :)
bashを排他的に使用する必要がありますか?私はこれを行う必要があり、LinuxとOS Xの違いにうんざりしていました。そのため、迅速で汚い解決策としてPHPを使用しました。
#!/usr/bin/php <-- or wherever
<?php
{
if($argc!=2)
exit();
$fname=$argv[1];
if(!file_exists($fname))
exit();
echo realpath($fname)."\n";
}
?>
私はそれがあまりエレガントな解決策ではないことを知っていますが、それは機能します。