상대 경로가 주어진 절대 경로를 검색하는 명령이 있습니까?
예를 들어 $ line에 dir에있는 각 파일의 절대 경로를 포함 시키려고합니다. ./etc/
find ./ -type f | while read line; do
echo $line
done
상대 경로가 주어진 절대 경로를 검색하는 명령이 있습니까?
예를 들어 $ line에 dir에있는 각 파일의 절대 경로를 포함 시키려고합니다. ./etc/
find ./ -type f | while read line; do
echo $line
done
답변:
시도하십시오 realpath
.
~ $ sudo apt-get install realpath # may already be installed
~ $ realpath .bashrc
/home/username/.bashrc
심볼릭 링크가 확장되지 않도록하려면을 사용하십시오 realpath -s
.
대답은 " 파일의 절대 경로를 인쇄하는 bash / fish 명령 "에서 나옵니다 .
realpath
Mac에서 사용할 수없는 것 같습니다 (OS X 10.11 "El Capitan"). :-(
realpath
CentOS 6에서도 사용할 수없는 것 같습니다
brew install coreutils
가져올 것이다realpath
realpath
이미 있습니다. 별도로 설치할 필요가 없었습니다.
realpath
Windows 용 Git에서 사용할 수 있습니다 (적어도 저에게는).
coreutils 패키지를 설치 한 경우 일반적으로 readlink -f relative_file_name
절대 패키지 를 검색하기 위해 사용할 수 있습니다 (모든 심볼릭 링크가 해결됨)
brew install coreutils
합니다. 그러나 실행 파일 앞에 ag가 붙습니다.greadlink -f relative_file_name
#! /bin/sh
echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"
UPD 몇 가지 설명
"$1"
dirname "$1"
cd "$(dirname "$1")
이 상대 디렉토리로 들어가서 pwd
쉘 명령 을 실행하여 절대 경로를 얻습니다.$(basename "$1")
echo
그것을realpath
또는 readlink -f
않습니다. 예를 들어 마지막 구성 요소가 심볼릭 링크 인 경로에서는 작동하지 않습니다.
-P
옵션을 제공 할 수 있습니다 pwd
.echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")"
가치있는 것에 대해, 나는 선정 된 답변에 투표했지만 해결책을 공유하고 싶었습니다. 단점은 Linux뿐입니다 .Stack overflow에 오기 전에 OSX와 동등한 것을 찾으려고 약 5 분이 걸렸습니다. 그래도 확실합니다.
Linux readlink -e
에서는와 함께 사용할 수 있습니다 dirname
.
$(dirname $(readlink -e ../../../../etc/passwd))
수확량
/etc/
그런 다음 dirname
자매 를 사용 basename
하여 파일 이름을 가져옵니다.
$(basename ../../../../../passwd)
수확량
passwd
다 합쳐서 ..
F=../../../../../etc/passwd
echo "$(dirname $(readlink -e $F))/$(basename $F)"
수확량
/etc/passwd
디렉토리를 타겟팅하는 경우 안전 basename
하고 아무것도 반환하지 않으며 최종 출력에서 이중 슬래시로 끝납니다.
dirname
, readlink
그리고 basename
. 이를 통해 목표가 아닌 기호 링크의 절대 경로를 얻을 수있었습니다.
/home/GKFX
나는 입력 touch newfile
I 입력 키를 누르기 전에 당신은 내 말 것을 해결할 수있다 "생성 / 홈 / GKFX / newfile에"아직 존재하지 않는 파일에 대한 절대 경로이다.
나는 이것이 가장 휴대용이라고 생각합니다.
abspath() {
cd "$(dirname "$1")"
printf "%s/%s\n" "$(pwd)" "$(basename "$1")"
cd "$OLDPWD"
}
경로가 존재하지 않으면 실패합니다.
dirname
이 뛰어나지 않으며 GNU 핵심 유틸리티입니다.
dirname
은 POSIX 표준 유틸리티입니다. pubs.opengroup.org/onlinepubs/9699919799/utilities/dirname.html
${1##*/}
하루 동안 사용하는 버전을 수정하려고 노력 했으며 이제 휴지통을 휴지통으로 바꿨 basename "$1"
으므로 마침내 /로 끝나는 경로를 올바르게 처리하는 것 같습니다.
../..
realpath
아마도 최고 일 것입니다
그러나 ...
초기 질문은 시작하기에 매우 혼란 스러웠으며, 언급 된 질문과 관련이없는 예가 있습니다.
선택한 답변은 실제로 제목의 모든 질문이 아니라 주어진 예제에 답변합니다. 첫 번째 명령은 그 대답입니다 (정말입니까? 의심 스럽습니다). '/'없이도 잘 할 수 있습니다. 그리고 두 번째 명령이 무엇을하는지 보지 못했습니다.
몇 가지 문제가 혼합되어 있습니다.
상대 경로 이름을 절대 경로로 변경합니다. ( 일반적으로와 같은 명령을 실행하는 경우 파일이 실제로 작성되기 전에 touch foo/bar
경로 이름이 foo/bar
있어야하며 계산에 사용되어야합니다. )
경로상의 심볼릭 링크 (symlink)로 인해 동일한 파일 (또는 잠재적 파일)을 나타내는 몇 개의 절대 경로 이름이있을 수 있지만 다른 이유로 인해 장치가 읽기 전용으로 두 번 마운트 될 수 있습니다. 그러한 심볼릭 링크를 명시 적으로 해결하거나 원하지 않을 수 있습니다.
심볼릭 링크가 아닌 파일 또는 이름에 대한 심볼릭 링크의 끝에 도달 이는 수행 방법에 따라 절대 경로 이름을 생성하거나 생성하지 않을 수 있습니다. 그리고 그것을 절대 경로 이름으로 해결하거나 원하지 않을 수 있습니다.
readlink foo
옵션이없는 명령 은 인수가있는 경우에만 답변을 제공합니다foo
가 기호 링크 인 하며 해당 응답은 해당 심볼릭 링크의 값입니다. 다른 링크는 따르지 않습니다. 대답은 상대 경로 일 수 있습니다. symlink 인수의 값이 무엇이든간에.
하나, readlink
모든 파일에 대해 작동하는 옵션 (-f -e 또는 -m)이 있으며 실제로 인수로 표시된 파일에 대한 하나의 절대 경로 이름 (심볼 링크가없는 경로 이름)을 제공합니다.
이것은 경로의 중간 심볼릭 링크를 해결하지 않고 절대 경로 이름을 사용하고자 할 수도 있지만 심볼릭 링크가 아닌 모든 것에 잘 작동합니다. 이것은 명령에 의해 수행됩니다realpath -s foo
symlink 인수의 경우 readlink
해당 옵션을 사용하면 인수의 절대 경로에있는 모든 symlink가 다시 해결되지만 인수 값에 따라 발생할 수있는 모든 symlink도 포함됩니다. 심볼릭 링크 자체에 대한 링크가 아닌 경로에 대한 절대 경로를 원한다면 원하지 않을 수도 있습니다. 다시 한 번 foo
심볼릭 링크 인 경우 realpath -s foo
인수로 제공된 심볼릭 링크를 포함하여 심볼릭 링크를 해결하지 않고 절대 경로를 얻습니다.
-s
옵션이 없으면 단순히 링크의 값을 읽는 것 외에 몇 가지 다른 것을 제외 realpath
하고는와 거의 동일
readlink
합니다. readlink
옵션이있는 이유 가 분명하지 않아서 바람직하지 않은 중복성을
realpath
만듭니다.
웹 탐색은 시스템마다 약간의 차이가있을 수 있다는 점을 제외하고는 더 이상 말하지 않습니다.
결론 : realpath
최소한 여기에 요청 된 용도에 대해 가장 유연하게 사용할 수있는 최상의 명령입니다.
내가 가장 좋아하는 솔루션이었다 사람 @EugenKonkov의 다른 유틸리티 (coreutils 패키지)가 있음을 의미하지 않기 때문입니다.
그러나 상대 경로 "."에 실패했습니다. ".."이므로이 특별한 경우를 처리하는 약간 개선 된 버전이 있습니다.
그러나 사용자 cd
에게 상대 경로의 상위 디렉토리에 대한 권한이 없으면 여전히 실패합니다 .
#! /bin/sh
# Takes a path argument and returns it as an absolute path.
# No-op if the path is already absolute.
function to-abs-path {
local target="$1"
if [ "$target" == "." ]; then
echo "$(pwd)"
elif [ "$target" == ".." ]; then
echo "$(dirname "$(pwd)")"
else
echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"
fi
}
Eugen의 대답은 저에게 효과적이지 않았지만 이것은 효과가있었습니다.
absolute="$(cd $(dirname \"$file\"); pwd)/$(basename \"$file\")"
참고로, 현재 작업 디렉토리는 영향을받지 않습니다.
가장 좋은 솔루션 인 imho는 https://stackoverflow.com/a/3373298/9724628에 게시 된 솔루션 입니다.
파이썬이 작동해야하지만 모든 경우 또는 대부분의 최신 사례를 다루고 휴대 성이 뛰어난 솔루션 인 것 같습니다.
python -c "import os,sys; print(os.path.realpath(sys.argv[1]))" path/to/file
python -c "import os,sys; print(os.path.abspath(sys.argv[1]))" path/to/file
당신은 어느 쪽도있다 맥 OS X에 bash에 사용하는 경우 realpath 존재하지이나 그 readlink를가 절대 경로를 인쇄 할 수 있습니다, 당신은 그것을 인쇄 선택하지만 코드에 자신의 버전이있을 수 있습니다. 내 구현은 다음과 같습니다.
(순수한 bash)
abspath(){
local thePath
if [[ ! "$1" =~ ^/ ]];then
thePath="$PWD/$1"
else
thePath="$1"
fi
echo "$thePath"|(
IFS=/
read -a parr
declare -a outp
for i in "${parr[@]}";do
case "$i" in
''|.) continue ;;
..)
len=${#outp[@]}
if ((len==0));then
continue
else
unset outp[$((len-1))]
fi
;;
*)
len=${#outp[@]}
outp[$len]="$i"
;;
esac
done
echo /"${outp[*]}"
)
}
(개크 사용)
abspath_gawk() {
if [[ -n "$1" ]];then
echo $1|gawk '{
if(substr($0,1,1) != "/"){
path = ENVIRON["PWD"]"/"$0
} else path = $0
split(path, a, "/")
n = asorti(a, b,"@ind_num_asc")
for(i in a){
if(a[i]=="" || a[i]=="."){
delete a[i]
}
}
n = asorti(a, b, "@ind_num_asc")
m = 0
while(m!=n){
m = n
for(i=1;i<=n;i++){
if(a[b[i]]==".."){
if(b[i-1] in a){
delete a[b[i-1]]
delete a[b[i]]
n = asorti(a, b, "@ind_num_asc")
break
} else exit 1
}
}
}
n = asorti(a, b, "@ind_num_asc")
if(n==0){
printf "/"
} else {
for(i=1;i<=n;i++){
printf "/"a[b[i]]
}
}
}'
fi
}
(순수한 bsd awk)
#!/usr/bin/env awk -f
function abspath(path, i,j,n,a,b,back,out){
if(substr(path,1,1) != "/"){
path = ENVIRON["PWD"]"/"path
}
split(path, a, "/")
n = length(a)
for(i=1;i<=n;i++){
if(a[i]==""||a[i]=="."){
continue
}
a[++j]=a[i]
}
for(i=j+1;i<=n;i++){
delete a[i]
}
j=0
for(i=length(a);i>=1;i--){
if(back==0){
if(a[i]==".."){
back++
continue
} else {
b[++j]=a[i]
}
} else {
if(a[i]==".."){
back++
continue
} else {
back--
continue
}
}
}
if(length(b)==0){
return "/"
} else {
for(i=length(b);i>=1;i--){
out=out"/"b[i]
}
return out
}
}
BEGIN{
if(ARGC>1){
for(k=1;k<ARGC;k++){
print abspath(ARGV[k])
}
exit
}
}
{
print abspath($0)
}
예:
$ abspath I/am/.//..//the/./god/../of///.././war
/Users/leon/I/the/war
상대 경로가 디렉토리 경로이면 내 시도가 가장 좋습니다.
absPath=$(pushd ../SOME_RELATIVE_PATH_TO_Directory > /dev/null && pwd && popd > /dev/null)
echo $absPath
echo "mydir/doc/ mydir/usoe ./mydir/usm" | awk '{ split($0,array," "); for(i in array){ system("cd "array[i]" && echo $PWD") } }'
@ ernest-a의 오히려 좋은 버전 개선 :
absolute_path() {
cd "$(dirname "$1")"
case $(basename $1) in
..) echo "$(dirname $(pwd))";;
.) echo "$(pwd)";;
*) echo "$(pwd)/$(basename $1)";;
esac
}
제대로 경로의 마지막 요소 인 케이스, 거래 ..
하는 경우 "$(pwd)/$(basename "$1")"
에 @ 어니스트-A의 대답은로를 통해 올 것이다 accurate_sub_path/spurious_subdirectory/..
.
이것은 realpath
설치되지 않았거나 오류 코드와 함께 종료되어 실패한 경우와 같이 다른 모든 것의 체인 솔루션입니다 . 그런 다음 경로를 올바르게 얻을 때까지 다음 솔루션을 시도합니다.
#!/bin/bash
function getabsolutepath() {
local target;
local changedir;
local basedir;
local firstattempt;
target="${1}";
if [ "$target" == "." ];
then
printf "%s" "$(pwd)";
elif [ "$target" == ".." ];
then
printf "%s" "$(dirname "$(pwd)")";
else
changedir="$(dirname "${target}")" && basedir="$(basename "${target}")" && firstattempt="$(cd "${changedir}" && pwd)" && printf "%s/%s" "${firstattempt}" "${basedir}" && return 0;
firstattempt="$(readlink -f "${target}")" && printf "%s" "${firstattempt}" && return 0;
firstattempt="$(realpath "${target}")" && printf "%s" "${firstattempt}" && return 0;
# If everything fails... TRHOW PYTHON ON IT!!!
local fullpath;
local pythoninterpreter;
local pythonexecutables;
local pythonlocations;
pythoninterpreter="python";
declare -a pythonlocations=("/usr/bin" "/bin");
declare -a pythonexecutables=("python" "python2" "python3");
for path in "${pythonlocations[@]}";
do
for executable in "${pythonexecutables[@]}";
do
fullpath="${path}/${executable}";
if [[ -f "${fullpath}" ]];
then
# printf "Found ${fullpath}\\n";
pythoninterpreter="${fullpath}";
break;
fi;
done;
if [[ "${pythoninterpreter}" != "python" ]];
then
# printf "Breaking... ${pythoninterpreter}\\n"
break;
fi;
done;
firstattempt="$(${pythoninterpreter} -c "import os, sys; print( os.path.abspath( sys.argv[1] ) );" "${target}")" && printf "%s" "${firstattempt}" && return 0;
# printf "Error: Could not determine the absolute path!\\n";
return 1;
fi
}
printf "\\nResults:\\n%s\\nExit: %s\\n" "$(getabsolutepath "./asdfasdf/ asdfasdf")" "${?}"
상대 경로 $ line에 bash 문자열 대체를 사용할 수 있습니다.
line=$(echo ${line/#..\//`cd ..; pwd`\/})
line=$(echo ${line/#.\//`pwd`\/})
echo $line
기본 문자열 앞쪽 대체는 공식
$ {string / # substring / replacement}
를 따릅니다 . https://www.tldp.org/LDP/abs/html/string-manipulation.html
\
문자가를 부정 /
우리는 우리가 찾기 / 대체하는 문자열의 일부가 될하고자 할 때.
Mac OS Catalina, Ubuntu 16 및 Centos 7 사이에서 깔끔하게 이식 가능한 솔루션을 찾을 수 없었기 때문에 파이썬 인라인으로 작업하기로 결정했으며 내 bash 스크립트에서 잘 작동했습니다.
to_abs_path() {
python -c "import os; print os.path.abspath('$1')"
}
to_abs_path "/some_path/../secrets"