Komut dosyamın argümanları olarak bazı dosya yolları var. Elbette bunlar göreceli olabilir (veya ~ içerebilir). Ancak yazdığım işlevler için mutlak, ancak sembolik bağları çözülmemiş yollara ihtiyacım var.
Bunun için herhangi bir işlev var mı?
Komut dosyamın argümanları olarak bazı dosya yolları var. Elbette bunlar göreceli olabilir (veya ~ içerebilir). Ancak yazdığım işlevler için mutlak, ancak sembolik bağları çözülmemiş yollara ihtiyacım var.
Bunun için herhangi bir işlev var mı?
readlink
sembolik bağları çözer; OP bunu istemiyor.
echo $(cd some_directory && pwd)
, symlink çözümleme, bazı_dizinler yoksa başarısız olur. çalışma dizini etkilenmez. veya bir değişkene atayın MY_PATH=$(cd some_directory && pwd)
.
Yanıtlar:
MY_PATH=$(readlink -f $YOUR_ARG)
"./"
ve gibi göreli yolları çözecek"../"
Bunu da düşünün ( kaynak ):
#!/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 Fiziksel mevcut çalışma dizinini görüntüleyin (tüm sembolik bağlantılar çözüldü)", sadece-P
readlink -f
OS X'de işlevselliği elde etmek için Homebrew'i kullanabilir ve ardından çalıştırabilirsiniz: $ brew install coreutils
Daha sonra kullanabilirsiniz greadlink -f
.
http://www.linuxquestions.org/questions/programming-9/bash-script-return-full-path-and-filename-680368/page3.html aşağıdakilere sahiptir
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
}
Kullanışlı olduğu bir duruma girmek için pushd
/ kullanır .popd
pwd
DIRSTACK
ve başka bir şey değil. Güzel çözüm!
sh
uyumluluğu hedeflerken, pushd; cd <dir>; <cmd>; popd
ile değiştirilebilir (cd <dir>; <cmd>)
.
Basit tek astar:
function abs_path {
(cd "$(dirname '$1')" &>/dev/null && printf "%s/%s" "$PWD" "${1##*/}")
}
Kullanım:
function do_something {
local file=$(abs_path $1)
printf "Absolute path to %s: %s\n" "$1" "$file"
}
do_something $HOME/path/to/some\ where
Hala yolun var olup olmadığından tamamen habersiz olmasını nasıl sağlayabileceğimi anlamaya çalışıyorum (bu nedenle dosya oluştururken de kullanılabilir).
cd -
sonra sıfırlamam gerekir mi?
${1##*/}
birlikte basename
, ayrı bir değişkene koymadan, boşluklu yollar düzgün çalışmıyor.
$PWD
ve oradan geçerseniz,
OS X'te kullanabilirsiniz
stat -f "%N" YOUR_PATH
linux üzerinde realpath
çalıştırılabilir dosyanız olabilir . değilse, aşağıdakiler işe yarayabilir (yalnızca bağlantılar için değil):
readlink -c YOUR_PATH
stat -f "%N" PATH
bana tam olarak verdiğim yolu veriyor.
Belki bu daha okunabilirdir ve bir alt kabuk kullanmaz ve mevcut dizini değiştirmez:
dir_resolve() {
local dir=`dirname "$1"`
local file=`basename "$1"`
pushd "$dir" &>/dev/null || return $? # On error, return error code
echo "`pwd -P`/$file" # output full, link-resolved path with filename
popd &> /dev/null
}
kendi kendine düzenleme, OP'nin çözülmüş sembolik bağlantıları aramadığını söylediğini fark ettim:
"Ancak yazdığım işlevler için mutlak, ancak sembolik bağları çözülmemiş yollara ihtiyacım var."
Öyleyse tahmin et bu onun sorusuna pek de uygun değil. :)
Yıllar boyunca bununla birçok kez karşılaştığım için ve bu sefer OSX ve linux üzerinde kullanabileceğim saf bir bash taşınabilir versiyona ihtiyacım vardı, devam ettim ve bir tane yazdım:
Canlı versiyon burada yaşıyor:
https://github.com/keen99/shell-functions/tree/master/resolve_path
ancak SO adına, işte mevcut sürüm (iyi test edildiğini düşünüyorum ... ancak geri bildirime açığım!)
Plain bourne shell (sh) için çalışmasını sağlamak zor olmayabilir, ama denemedim ... $ FUNCNAME'i çok seviyorum. :)
#!/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
}
İşte demleme sayesinde klasik bir örnek:
%% 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
bu işlevi kullanın ve -gerçek- yolunu döndürecektir:
%% 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
İşletim sisteminiz destekliyorsa, şunu kullanın:
realpath "./some/dir"
Ve bir değişkende kullanmak:
some_path="$(realpath "./some/dir")"
Yolunuzu genişletecek. Ubuntu ve CentOS üzerinde test edilmiştir, sizde bulunmayabilir. Bazıları readlink'i öneriyor, ancak readlink için dokümantasyon şöyle diyor:
Realpath (1) 'in, standartlaştırma işlevselliği için kullanılması tercih edilen komuttur.
İnsanlar neden değişkenlerimden alıntı yaptığımı merak ederse, yollardaki boşlukları korumaktır. Gibi yapıyor realpath some path
size iki farklı yol sonuçlar verecektir. Ama realpath "some path"
bir tane dönecek. Alıntılanan parametreler ftw :)
Sadece bash kullanmak zorunda mısınız? Bunu yapmam gerekiyordu ve Linux ile OS X arasındaki farklılıklardan bıktım. Bu yüzden hızlı ve kirli bir çözüm için PHP'yi kullandım.
#!/usr/bin/php <-- or wherever
<?php
{
if($argc!=2)
exit();
$fname=$argv[1];
if(!file_exists($fname))
exit();
echo realpath($fname)."\n";
}
?>
Çok zarif bir çözüm olmadığını biliyorum ama işe yarıyor.