배쉬 : 주어진 상대 경로를 검색
상대 경로가 주어진 절대 경로를 검색하는 명령이 있습니까?
예를 들어 $ line에 dir에있는 각 파일의 절대 경로를 포함 시키려고합니다. ./etc/
find ./ -type f | while read line; do
echo $line
done
사용하다:
find $(pwd)/ -type f
모든 파일을 얻거나
echo $(pwd)/$line
전체 경로 표시 (상대 경로가 중요한 경우)
시도하십시오 realpath
.
~ $ sudo apt-get install realpath # may already be installed
~ $ realpath .bashrc
/home/username/.bashrc
심볼릭 링크가 확장되지 않도록하려면을 사용하십시오 realpath -s
.
대답은 " 파일의 절대 경로를 인쇄하는 bash / fish 명령 "에서 나옵니다 .
coreutils 패키지를 설치 한 경우 일반적으로 readlink -f relative_file_name
절대 패키지 를 검색하기 위해 사용할 수 있습니다 (모든 심볼릭 링크가 해결됨)
#! /bin/sh
echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"
UPD 몇 가지 설명
- 이 스크립트는 상대 경로를 인수로 얻습니다.
"$1"
- 그런 다음 해당 경로의 dirname 부분을 얻습니다 (dir 또는 file을이 스크립트에 전달할 수 있음).
dirname "$1"
- 그런 다음
cd "$(dirname "$1")
이 상대 디렉토리로 들어가서pwd
쉘 명령 을 실행하여 절대 경로를 얻습니다. - 그런 다음 절대 경로에 기본 이름 을 추가 합니다.
$(basename "$1")
- 마지막 단계는 우리로
echo
그것을
가치있는 것에 대해, 나는 선정 된 답변에 투표했지만 해결책을 공유하고 싶었습니다. 단점은 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
하고 아무것도 반환하지 않으며 최종 출력에서 이중 슬래시로 끝납니다.
나는 이것이 가장 휴대용이라고 생각합니다.
abspath() {
cd "$(dirname "$1")"
printf "%s/%s\n" "$(pwd)" "$(basename "$1")"
cd "$OLDPWD"
}
경로가 존재하지 않으면 실패합니다.
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
여기에 요청 된 용도에 대해 가장 유연하게 사용할 수있는 최상의 명령입니다.
Eugen의 대답은 나에게 효과적이지 않았지만 이것은 효과가있었습니다.
absolute="$(cd $(dirname \"$file\"); pwd)/$(basename \"$file\")"
참고로, 현재 작업 디렉토리는 영향을받지 않습니다.
내가 가장 좋아하는 솔루션은 @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
}
의 경우 find
검색 할 절대 경로를 지정하는 것이 가장 쉬운 방법입니다. 예 :
find /etc
find `pwd`/subdir_of_current_dir/ -type f
당신은 어느 쪽도있다 맥 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
가장 좋은 솔루션 인 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
find $PWD
또는 bash를 제외하고 그들이 말한 find ~+
것이 조금 더 편리합니다.
Similar to @ernest-a's answer but without affecting $OLDPWD
or define a new function you could fire a subshell (cd <path>; pwd)
$ pwd
/etc/apache2
$ cd ../cups
$ cd -
/etc/apache2
$ (cd ~/..; pwd)
/Users
$ cd -
/etc/cups
If the relative path is a directory path, then try mine, should be the best:
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") } }'
If you want to transform a variable containing a relative path into an absolute one, this works :
dir=`cd "$dir"`
"cd" echoes without changing the working directory, because executed here in a sub-shell.
This is a chained solution from all others, for example, when realpath
fails, either because it is not installed or because it exits with error code, then, the next solution is attempted until it get the path right.
#!/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")" "${?}"
참고URL : https://stackoverflow.com/questions/4175264/bash-retrieve-absolute-path-given-relative
'IT' 카테고리의 다른 글
설치된 모든 node.js 모듈 목록을 인쇄하십시오. (0) | 2020.07.03 |
---|---|
String 객체를 Hash 객체로 어떻게 변환합니까? (0) | 2020.07.03 |
월말 계산 (0) | 2020.07.03 |
여러 값과 같은 MySQL (0) | 2020.07.03 |
mongo-서버 127.0.0.1:27017에 연결할 수 없습니다 (0) | 2020.07.03 |