셸(BASH/ZSH/SH)을 통해 파일의 절대 경로를 얻는 방법은 무엇입니까?
질문: 입력하는 파일의 절대 경로를 인쇄하는 간단한 sh/bash/zsh/fish/... 명령이 있습니까?
사용 사례:전화번호부에 있습니다./a/b
파일의 전체 c
다른 에 쉽게 수 : 다 프 로 그 붙 명 있 에 사 서 있 수 니 습 다 할 용 줄 령 록 른 도 수 쉽 램 에 을 넣 여 게 니 ▁on 다 있 습 ▁the - :/a/b/c
단순하지만 약간의 프로그램을 사용하면 긴 경로를 처리할 때 5초 정도의 시간을 절약할 수 있습니다. 이는 결국 합산됩니다.이를 위한 표준 유틸리티를 찾을 수 없다는 것은 놀라운 일입니다. 정말로 없는 것일까요?
다음은 abspath.py 의 샘플 구현입니다.
#!/usr/bin/python
# Author: Diggory Hardy <diggory.hardy@gmail.com>
# Licence: public domain
# Purpose: print the absolute path of all input paths
import sys
import os.path
if len(sys.argv)>1:
for i in range(1,len(sys.argv)):
print os.path.abspath( sys.argv[i] )
sys.exit(0)
else:
print >> sys.stderr, "Usage: ",sys.argv[0]," PATH."
sys.exit(1)
사용
$ realpath example.txt
/home/username/example.txt
ㅠㅠreadlink
심볼릭 링크를 해결합니다.
readlink -e /foo/bar/baz
#! /bin/sh
echo "$(cd "$(dirname -- "$1")" >/dev/null; pwd -P)/$(basename -- "$1")"
잊버림은 요.readlink
그리고.realpath
시스템에 설치할 수도 있고 설치하지 않을 수도 있습니다.
위에서 개베인의 답변을 확장하면 다음과 같이 표현됩니다.
#!/bin/bash
get_abs_filename() {
# $1 : relative filename
echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")"
}
그러면 다음과 같이 사용할 수 있습니다.
myabsfile=$(get_abs_filename "../../foo/bar/file.txt")
어떻게 그리고 왜 작동합니까?
합니다.pwd
명령은 인수 없이 호출될 때 현재 디렉터리의 절대 경로를 인쇄합니다.
이 솔루션이 마음에 드는 이유는 무엇입니까?
휴대가 가능하며 두 가지 모두 필요하지 않습니다.readlink
또는realpath
특정 Linux/Unix 디스트리뷰터의 기본 설치에는 없는 경우가 많습니다.
만약 dir가 존재하지 않는다면요?
위에 주어진 것처럼 주어진 디렉터리 경로가 존재하지 않으면 함수가 실패하고 stderr에 인쇄됩니다.이것은 당신이 원하는 것이 아닐 수도 있습니다.이러한 상황을 처리하기 위해 기능을 확장할 수 있습니다.
#!/bin/bash
get_abs_filename() {
# $1 : relative filename
if [ -d "$(dirname "$1")" ]; then
echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")"
fi
}
이제 상위 dirs가 없는 경우 빈 문자열을 반환합니다.
입력에서 '...' 또는 '.' 뒤에 오는 것은 어떻게 처리합니까?
그런 경우에는 절대적인 경로를 제공하지만, 최소한의 경로는 아닙니다.다음과 같이 표시됩니다.
/Users/bob/Documents/..
'...'을(를) 해결하려면 스크립트를 다음과 같이 만들어야 합니다.
get_abs_filename() {
# $1 : relative filename
filename=$1
parentdir=$(dirname "${filename}")
if [ -d "${filename}" ]; then
echo "$(cd "${filename}" && pwd)"
elif [ -d "${parentdir}" ]; then
echo "$(cd "${parentdir}" && pwd)/$(basename "${filename}")"
fi
}
$ readlink -m FILE
/path/to/FILE
은 이은보낫습다니다것보다 더 .readlink -e FILE
또는realpath
파일이 없어도 작동하기 때문입니다.
절대 경로 변환기 셸 함수에 대한 상대 경로
- 하지 않습니다( 유리티단않다습니필지하요가틸,
cd
그리고.pwd
) - 디렉토리 및 파일에 대해 작동합니다.
- 손이
..
그리고..
- dir 또는 파일 이름의 공백을 처리합니다.
- 파일 또는 디렉토리가 있어야 합니다.
- 지정된 경로에 아무것도 없으면 아무것도 반환하지 않습니다.
- 절대 경로를 입력으로 처리합니다(기본적으로 경로 처리).
코드:
function abspath() {
# generate absolute path from relative path
# $1 : relative filename
# return : absolute path
if [ -d "$1" ]; then
# dir
(cd "$1"; pwd)
elif [ -f "$1" ]; then
# file
if [[ $1 = /* ]]; then
echo "$1"
elif [[ $1 == */* ]]; then
echo "$(cd "${1%/*}"; pwd)/${1##*/}"
else
echo "$(pwd)/$1"
fi
fi
}
샘플:
# assume inside /parent/cur
abspath file.txt => /parent/cur/file.txt
abspath . => /parent/cur
abspath .. => /parent
abspath ../dir/file.txt => /parent/dir/file.txt
abspath ../dir/../dir => /parent/dir # anything cd can handle
abspath doesnotexist => # empty result if file/dir does not exist
abspath /file.txt => /file.txt # handle absolute path input
참고: 이것은 nan6000과 bsingh의 답변을 기반으로 하지만 파일 케이스를 수정합니다.
또한 원래 질문은 기존 명령줄 유틸리티에 대한 것으로 알고 있습니다.하지만 이것이 최소한의 의존성을 갖기를 원하는 셸 스크립트를 포함한 스택 오버플로에 대한 질문인 것 같기 때문에, 저는 이 스크립트 솔루션을 여기에 두었습니다. 나중에 찾을 수 있도록 말입니다. :)
그find
명령이 도움이 될 수 있습니다.
find $PWD -name ex*
find $PWD -name example.log
패턴과 일치하는 이름을 가진 현재 디렉터리 또는 아래의 모든 파일을 나열합니다.몇 가지 결과(예: 몇 개의 파일이 포함된 트리 아래쪽 디렉터리)만 얻을 수 있다면 단순화할 수 있습니다.
find $PWD
Solaris 10에서 사용하는데, 여기에는 언급된 다른 유틸리티가 없습니다.
여기 콤팩트함 때문에 마음에 드는 zsh 전용 기능이 있습니다.'A' 확장 수식어를 사용합니다(zhexpn(1) 참조).
realpath() { for f in "$@"; do echo ${f}(:A); done }
readlink 또는 realpath 유틸리티가 없다면 bash와 zsh에서 작동하는 다음 기능을 사용할 수 있습니다(나머지는 잘 모르겠습니다).
abspath () { case "$1" in /*)printf "%s\n" "$1";; *)printf "%s\n" "$PWD/$1";; esac; }
하지 않는 파일에도 " " " " " " " (" " " " " " " " " ").os.path.abspath
).
도 불하게도행.abspath ./../somefile
점을 없애지 못합니다.
일반적으로 다음과 같은 것은 없습니다. absolute path
(이 진술은 일반적으로 둘 이상일 수 있으므로 명확한 조항의 사용이 적절하지 않다는 것을 의미합니다.)안absolute path
루트 "/"에서 시작하여 작업 디렉터리와 독립적으로 모호하지 않은 파일을 지정하는 경로입니다. (위키백과의 예 참조)
A relative path
다른 디렉터리에서 시작하여 해석되는 경로입니다.작업 디렉토리일 수 있습니다.relative path
(▁when 디렉토리의 심볼릭 때 으로 해당 에 두고 있을 수 ).디렉토리의 심볼릭 링크에 있는 경우, 디렉토리는 일반적으로 해당 디렉토리에 상대적으로 사용됩니다(사용자가 다른 용도를 염두에 두고 있을 수도 있음).
따라서 절대 경로는 루트 디렉터리에 상대적인 경로일 뿐입니다.
경로(절대 또는 상대)는 심볼릭 링크를 포함하거나 포함하지 않을 수 있습니다.그렇지 않은 경우에는 링크 구조의 변경에도 다소 영향을 미치지 않지만, 이는 반드시 필요한 것은 아니며 바람직하지도 않습니다.어떤 사람들은 전화합니다.canonical path
(또는)canonical file name
또는resolved path
한 사람absolute path
모든 심볼릭 링크가 해결되었습니다. 즉, 링크가 연결되는 경로로 대체되었습니다.는 " " 입니다.realpath
그리고.readlink
둘 다 표준 경로를 찾지만realpath
에는 심볼릭 링크를 확인하지 않고도 절대 경로를 얻을 수 있는 옵션이 있습니다(일부 디렉토리에 대해 절대 경로 또는 상대 경로를 가져올 수 있는 여러 가지 다른 옵션 포함).
여기에는 몇 가지 의견이 필요합니다.
- 심볼릭 링크는 링크해야 할 것이 이미 생성된 경우에만 해결될 수 있습니다. 이것은 분명히 항상 그렇지는 않습니다.는 " " 입니다.
realpath
그리고.readlink
그것을 설명할 수 있는 선택권이 있습니다. - 경로의 디렉터리는 나중에 심볼 링크가 될 수 있습니다. 즉, 경로가 더 이상
canonical
따라서 개념은 시간(또는 환경)에 의존합니다. - 링크가 이상적인 에도, 의 심볼릭 링크가 존재할 수 .
canonical path
다음 두 가지 이유로 파일에 저장합니다.- 수 (「 」 파일포동마수있을다니습었되트운시에파이티함션이된(▁have▁the다파▁cont있니▁partition▁simultane▁mounted▁may▁been습).
ro
마운트지점에 합니다.를 여러 마운트 지점에 배치합니다. - 파일에 대한 하드 링크가 있을 수 있습니다. 즉, 파일이 여러 개의 서로 다른 디렉토리에 존재한다는 것을 의미합니다.
- 수 (「 」 파일포동마수있을다니습었되트운시에파이티함션이된(▁have▁the다파▁cont있니▁partition▁simultane▁mounted▁may▁been습).
따라서, 훨씬 더 제한적인 정의에도 불구하고.canonical path
파일에 대한 표준 경로가 여러 개 있을 수 있습니다. 이또한자가정한을 합니다.canonical
일반적으로 고유성의 개념을 내포하기 때문에 다소 부적절합니다.
이것은 Bash의 또 다른 유사한 질문에 대한 답변에서 주제에 대한 간단한 토론을 확장합니다: 상대적으로 주어진 절대 경로 검색.
은 내결은입니다.realpath
보다 더 잘 설계되었으며 훨씬 더 유연합니다.readlink
의 readlink
은 을받용않는지의 .realpath
기호 링크의 값을 반환하는 옵션이 없는 호출입니다.
기본 제공 기능만 사용하려는 경우 가장 단순한 방법은 다음과 같습니다.
find `pwd` -name fileName
두 단어만 더 입력하면 OSX뿐만 아니라 모든 유닉스 시스템에서 작동합니다.
그dogbane
설명과 함께 다음과 같이 답변합니다.
#! /bin/sh
echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"
설명:
- 이 스 립 경 인 가 옵 니 져 다 로 로써 상대 .
"$1"
- 그런 다음 경로의 dirname 부분을 가져옵니다(이 스크립트에 dir 또는 파일을 전달할 수 있습니다).
dirname "$1"
- 그러면 저희가.
cd "$(dirname "$1")
인 dir로 이상로인들어실서행가다얻절써니습경로대로으를함대적▁path▁를 실행하여 절대 경로를 .pwd
명령어 - 명령어 - 그런 다음 절대 경로에 기본 이름을 추가합니다.
$(basename "$1")
- 마지막 단계로 우리는
echo
그것
이 질문의 상위 답변은 경우에 따라 오해를 불러일으킬 수 있습니다.당이찾고하절경있파이일는에 .$PATH
변수:
# node is in $PATH variable
type -P node
# /home/user/.asdf/shims/node
cd /tmp
touch node # But because there is a file with the same name inside the current dir check out what happens below
readlink -e node
# /tmp/node
readlink -m node
# /tmp/node
readlink -f node
# /tmp/node
echo "$(cd "$(dirname "node")"; pwd -P)/$(basename "node")"
# /tmp/node
realpath node
# /tmp/node
realpath -e node
# /tmp/node
# Now let's say that for some reason node does not exist in current directory
rm node
readlink -e node
# <nothing printed>
readlink -m node
# /tmp/node # Note: /tmp/node does not exist, but is printed
readlink -f node
# /tmp/node # Note: /tmp/node does not exist, but is printed
echo "$(cd "$(dirname "node")"; pwd -P)/$(basename "node")"
# /tmp/node # Note: /tmp/node does not exist, but is printed
realpath node
# /tmp/node # Note: /tmp/node does not exist, but is printed
realpath -e node
# realpath: node: No such file or directory
위에 근거하여 저는 다음과 같은 결론을 내릴 수 있습니다.realpath -e
그리고.readlink -e
변수의 영향을 받지 않고 현재 디렉터리에 존재할 것으로 예상되는 파일의 절대 경로를 찾는 데 사용할 수 있습니다.유일한 차이점은realpath
수 없는 둘 다 합니다. stderr 출 력 하 파 오 다 코 반 환 합 니 를 다 드 류 둘 경 우 로 는 없 수 을 지 찾 만 일 을 ▁code
cd /tmp
rm node
realpath -e node ; echo $?
# realpath: node: No such file or directory
# 1
readlink -e node ; echo $?
# 1
에 존재하는 파일의 절대 경로 a를 원하는 경우, 다음 명령은 이름이 같은 파일이 current dir에 존재하는지 여부에 관계없이 적합합니다.
type -P example.txt
# /path/to/example.txt
# Or if you want to follow links
readlink -e $(type -P example.txt)
# /originalpath/to/example.txt
# If the file you are looking for is an executable (and wrap again through `readlink -e` for following links )
which executablefile
# /opt/bin/executablefile
그리고 a, 누락된 경우 폴백, 예:
cd /tmp
touch node
echo $(readlink -e node || type -P node)
# /tmp/node
rm node
echo $(readlink -e node || type -P node)
# /home/user/.asdf/shims/node
홈브루로 답하기
realpath
되어 있지 가장좋대답지만설않경먼를합실니다저야행을 해야 합니다.brew install coreutils
멋진 기능을 가진 코어 유틸리티를 설치할 것입니다.사용자 지정 기능을 작성하고 내보내는 것은 이와 같은 경우 작업이 너무 많고 오류가 발생할 위험이 있습니다. 여기 두 줄이 있습니다.
$ brew install coreutils
$ realpath your-file-name.json
의 경우dirname
넘지 다 어 려 지 다../
와리즈턴을 반환합니다../
.
nonlan6000의 함수는 다음을 수정할 수 없습니다.
get_abs_filename() {
# $1 : relative filename
if [ -d "${1%/*}" ]; then
echo "$(cd ${1%/*}; pwd)/${1##*/}"
fi
}
이는 질문에 대한 답변이 아니라 스크립팅을 수행하는 사용자를 위한 것입니다.
echo `cd "$1" 2>/dev/null&&pwd||(cd "$(dirname "$1")";pwd|sed "s|/*\$|/${1##*/}|")`
/.../ 등을 올바르게 처리합니다.저도 OSX에서 일하는 것 같습니다.
시스템에 다음 스크립트를 배치했으며 현재 dir에 있는 파일의 전체 경로를 빠르게 가져오고 싶을 때 이 스크립트를 bash 별칭이라고 합니다.
#!/bin/bash
/usr/bin/find "$PWD" -maxdepth 1 -mindepth 1 -name "$1"
왜 OS X에서 스크립트 "$PWD"가 호출되면 절대 경로로 확장되는지는 잘 모르겠습니다.찾기 명령이 명령줄에서 호출되면 호출되지 않습니다.하지만 내가 원하는 건...즐거운 시간 되세요.
#! /bin/bash
file="$@"
realpath "$file" 2>/dev/null || eval realpath $(echo $file | sed 's/ /\\ /g')
은 이은의단보다니완의 단점을 입니다.realpath
스크립트에 합니다.fullpath
이제 전화할 수 있습니다.
$ cd && touch a\ a && rm A 2>/dev/null
$ fullpath "a a"
/home/user/a a
$ fullpath ~/a\ a
/home/user/a a
$ fullpath A
A: No such file or directory.
Ruby에서 절대 경로를 얻을 수 있는 대안:
realpath() {ruby -e "require 'Pathname'; puts Pathname.new('$1').realpath.to_s";}
인수(현재 폴더) 없이 상대 및 절대 파일 또는 폴더 경로를 인수로 지정하여 작동합니다.
스크립트가 bash 또는 bash 호환 셸이 존재한다고 주장할 수 있다면 Alexander Klimetscheck의 답변은 괜찮습니다.POSIX만 준수하는 셸에서는 작동하지 않습니다.
최종 root에 일 경우 은 " " " " 입니다.//file
으로 정확하지 않은 입니다. (더블의 경우에는 (더블의 경우)/
시스템에 의해 싱글로 취급됨) 하지만 이상하게 보입니다.
다음은 모든 POSIX 호환 셸에서 작동하는 버전이며, 사용 중인 모든 외부 도구는 POSIX 표준에 의해 요구되며 루트 파일 대소문자를 명시적으로 처리합니다.
#!/bin/sh
abspath ( ) {
if [ ! -e "$1" ]; then
return 1
fi
file=""
dir="$1"
if [ ! -d "$dir" ]; then
file=$(basename "$dir")
dir=$(dirname "$dir")
fi
case "$dir" in
/*) ;;
*) dir="$(pwd)/$dir"
esac
result=$(cd "$dir" && pwd)
if [ -n "$file" ]; then
case "$result" in
*/) ;;
*) result="$result/"
esac
result="$result$file"
fi
printf "%s\n" "$result"
}
abspath "$1"
이 파일을 파일에 저장하고 실행 파일로 만들면 파일 및 디렉터리의 절대 경로를 빠르게 가져올 수 있는 CLI 도구가 있습니다.또는 기능을 복사하여 자체 POSIX 호환 스크립트에서 사용할 수 있습니다.상대 경로를 절대 경로로 바꾸고 절대 경로를 그대로 반환합니다.
흥미로운 수정 사항:
을 result=$(cd "$dir" && pwd)
와 함께result=$(cd "$dir" && pwd -P)
그러면 최종 파일의 경로에 있는 모든 심볼릭 링크도 해결됩니다.
첫 번째 수정에 관심이 없는 경우 조기에 반환하여 절대 대소문자를 최적화할 수 있습니다.
abspath ( ) {
if [ ! -e "$1" ]; then
return 1
fi
case "$1" in
/*)
printf "%s\n" "$1"
return 0
esac
file=""
dir="$1"
if [ ! -d "$dir" ]; then
file=$(basename "$dir")
dir=$(dirname "$dir")
fi
result=$(cd "$dir" && pwd)
if [ -n "$file" ]; then
case "$result" in
*/) ;;
*) result="$result/"
esac
result="$result$file"
fi
printf "%s\n" "$result"
}
그리고 의문이 생길 것이기 때문에:왜죠printf
에 echo
?
echo
기본적으로 사용자가 stdout할 메시지를 인쇄합니다..echo
스크립트 작성자가 의존하는 동작은 사실 지정되지 않았습니다. 유명한 유한사도람들명▁the▁even도.-n
또는 의 이 가능합니다.\t
다음과 같습니다.POSIX 표준은 다음과 같습니다.
표준 출력에 쓸 문자열입니다.첫 번째 피연산자가 -n이거나 피연산자 중 하나에 문자가 포함되어 있으면 결과가 구현 정의됩니다.
- https://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html
를 쓰고 할 만한 것을 사용하는 것이 .printf
의 printf
정확히 정의되어 있습니다.하는데, 사용자에게 stdout만 합니다. 이것은 사용자를 위한 메시지가 아니므로 다음만 사용합니다.printf
완벽한 휴대성을 보장합니다.
저는 단일 회선을 사용합니다.
(cd ${FILENAME%/*}; pwd)
그러나 이는 다음과 같은 경우에만 사용할 수 있습니다.$FILENAME
실제 존재하는 모든 종류의 선행 경로(즉, 절대 경로)가 있습니다.선도적인 경로가 전혀 없는 경우, 답은 간단히 다음과 같습니다.$PWD
수, 답은 선행경로존않답수있불며, 그렇않단다니합순답은면으으지확할실이가으면재지하▁simply▁if▁does다▁is니▁answer▁be단합입니다.${FILENAME%/*}
경로가 절대적인 경우
이 모든 것을 종합하면 다음 기능을 사용할 것을 제안합니다.
function abspath() {
# argument 1: file pathname (relative or absolute)
# returns: file pathname (absolute)
if [ "$1" == "${1##*/}" ]; then # no path at all
echo "$PWD"
elif [ "${1:0:1}" == "/" -a "${1/../}" == "$1" ]; then # strictly absolute path
echo "${1%/*}"
else # relative path (may fail if a needed folder is non-existent)
echo "$(cd ${1%/*}; pwd)"
fi
}
또한 이 기능은 다음과 같은 경우에만 사용할 수 있습니다.bash
그리고 호환 가능한 껍질.한 셸에서 합니다.sh
.
여러분, 저는 그것이 오래된 스레드라는 것을 알지만 저처럼 이것을 방문한 다른 사람들에게 참고하기 위해 이것을 게시합니다.만약 내가 질문을 올바르게 이해했다면, 나는 생각합니다.locate $filename
제공된 합니다.제공된 파일의 절대 경로가 표시되지만 파일이 있는 경우에만 표시됩니다.
언급URL : https://stackoverflow.com/questions/3915040/how-to-obtain-the-absolute-path-of-a-file-via-shell-bash-zsh-sh
'programing' 카테고리의 다른 글
ASP 변환 방법.NET 웹 사이트에서 ASP로.NET 웹 애플리케이션 (0) | 2023.05.08 |
---|---|
VB.NET 빈 문자열 배열 (0) | 2023.05.08 |
VB에서 암시적 변환 연산자를 정의하는 방법이 있습니까?NET? (0) | 2023.05.08 |
빈 슬라이스를 초기화하는 올바른 방법 (0) | 2023.05.08 |
AttributeError: 부분적으로 초기화된 모듈을 수정하는 방법? (0) | 2023.05.08 |