답변1
realpath
내 머리로는 이러한 유틸리티 중 어느 것도 사양에서 이 기능을 참조하고 있는지 모르겠습니다 .
내가 아는 전부는시험디렉토리 항목의 경우경로 이름은 기존 디렉토리 항목으로 확인됩니다.1+x.
Peep에서의 구현대시(git.kernel.org), 그것은 사용lstat64/stat64.
이것은 디렉토리에 충분할 수 있습니다(시험-디경로명) 도착하다CD그 안으로 들어가서 확인된 경로 이름을 반환합니다.비밀번호.
~을 위한CD,CD 경로설정되지 않거나 비어 있어야 하며² 피연산자는 하이픈 빼기 기호가 아니어야 합니다."-".³
([ -d "$1" ] && [ '-' != "$1" ] && CDPATH= cd -P -- "$1" && pwd -P)
예:디렉터리의 절대 경로, 정식 경로, 실제 경로 이름을 반환하거나, 디렉터리로 확인되지 않은 경우 null을 반환합니다.
경로 이름에서 하이픈 빼기 기호("-")를 제외하는 데 문제가 있는 경우 대안은 피연산자를 "./-"로 설정하는 것입니다.
1 참조시험² 참조CD 5단계 지침, 참조.cd "-" 피연산자
읽어보니 이미 아시는군요디렉토리 이름그리고기본 이름, 그리고 아마도 어떻게기호 링크가 끊어졌거나 존재하지 않는지 확인하십시오. Unix & Linux, 그렇지 않다면 해당 답변의 맥락을 확인하여 관심이 있는지 확인하세요."시험구별 등의 사용법테스트 -d 경로 이름1. 종료 상태
답변2
질문을 게시한 후 다음과 같은 해결 방법을 생각해 냈습니다.
#!/bin/sh
realpath() (
file=
path=$1
[ -d "$path" ] || {
file=/$(basename -- "$path")
path=$(dirname -- "$path")
}
{
path=$(cd -- "$path" && pwd)$file
} || exit $?
printf %s\\n "/${path#"${path%%[!/]*}"}"
)
경고: 분명히 지금까지 이만큼 테스트할 수 없었습니다! 항상 피드백을 요청하세요. 혹시 보신 분 계시면 댓글 남겨주세요.
또한 다른 사람들도 이전에 같은 아이디어를 가지고 있었고 특히 극단적인 경우와 광범위한 테스트 후에 더 잘 해결했다고 확신합니다. 더 알고 계시다면 링크를 올려주세요.
위의 셸 기능은 realpath
GNU coreutils를 대체합니다 realpath -s --
.https://www.gnu.org/software/coreutils/manual/html_node/realpath-inplication.html. 이는 심볼릭 링크가 해결되지 않았음을 의미합니다. (상대 경로 해결에만 관심이 있는 경우에도 이는 필요하지 않습니다.)
-
#!/bin/sh
Shebang을 POSIX 쉘로 사용하십시오.
-
realpath() (
realpath() (...)
대신 에 서브셸에서 함수를 실행 하면realpath() {...}
존재할 수 있는file
변수를 덮어쓰지 않습니다path
. (POSIX 쉘은 지역 변수를 지원하지 않습니다.) -
file= path=$1
변수를 정의합니다. 처음에는 인수에 의해 제공된 경로가
$1
기존 디렉터리라고 가정합니다. (경로의 마지막 구성 요소가 제거하려는 경로의 반대 부분인.
또는 일 수 있기 때문에 이는 중요합니다.)..
-
[ -d "$path" ] || { file=/$(basename -- "$path") path=$(dirname -- "$path") }
함수 인수가 이전에 가정한 대로 기존 디렉터리에 대한 경로가 아닌 경우
$path
Quote from 을 조정해야 합니다man realpath
.확인된 절대 파일 이름을 인쇄합니다. 마지막 구성 요소를 제외하고 모두 존재해야 합니다.
$file
따라서 ("마지막 구성 요소")가 실제로 기존 파일인지, 존재하지 않는 파일이나 폴더인지는 중요하지 않습니다.$path
이제 삭제하고 결국 다시 첨부하겠습니다. -
{ path=$(cd -- "$path" && pwd)$file
여기서 "트릭"이 발생합니다. 상대 경로를 해결하려면 해당 경로
cd
를 구문 분석하고pwd
최종 디렉토리를 인쇄하는 데 사용하면 됩니다. 이 새로운 경로는$path
.2.6.3 명령 대체서브셸에서 실행합니다.$file
마지막에 첨부됩니다. -
} || exit $?
{...}
이 줄은 이전 줄의 변수 할당을 둘러싼 코드 블록의 이유입니다. 사용자가 잘못된 경로를 제공하는 경우(예: 마지막 구성 요소만 존재하지 않는 경우),cd
(명령 대체 내에서) 실패하고 stderr에 오류 메시지를 인쇄해야 합니다(예: "...로 CD할 수 없습니다."). 오류 코드 > 0으로 종료합니다. 이는 명령 대체 서브쉘에 대한 오류 코드이기도 합니다. 이 오류 코드에 액세스하려면$?
변수 할당이 래핑됩니다{...}
. 따라서{...}
블록이 실패하면 함수를 종료하고 0이 아닌 동일한 오류 코드를 전파합니다. -
printf %s\\n "/${path#"${path%%[!/]*}"}"
//
또는 존재하지 않는/a
것과 같은 극단적인 경우로 인해 결과는 또는a
입니다 . 그래서//
//a
2.6.2 매개변수 확장$path
최종 출력에 단일 슬래시를 추가하기 전에 에서 모든 선행 슬래시를 제거하는 데 사용됩니다 .
제가 실행한 몇 가지 테스트는 다음과 같습니다.
for path in / // /// . .. "$HOME/." "$HOME/.." "*" --help /tmp /notexisting
do
if [ "$(realpath "$path")" != "$(/usr/bin/realpath -s -- "$path")" ]
then
printf %s\\n "$path"
fi
done