readlink
심볼릭 링크를 사용하여 일반 파일을 얻는 방법을 알 수도 있습니다 . $@
내 함수에 전달된 심볼릭 링크를 다음과 같이 바꾸는 매우 기본적인 아이디어가 있습니다 .
for file in "$@"; do
[ -L "$file" ] && file=$(readlink -f "$file")
done
예를 들면 SymLink 입니다 /etc/os-release -> ../usr/lib/os-release
.
하지만 이렇게 하면:
set -- '/etc/os-release'; for file in "$@"; do [ -L "$file" ] && file=$(readlink -f "$file"); done; echo "$@"
여전히 원래 SymLink 경로를 얻을 수 있는데 이는 실망스럽습니다. 직접 수정하고 싶은데 $@
불가능하다면 해결책이 없을까요?
답변1
원본 코드:
for file in "$@"; do
[ -L "$file" ] && file=$(readlink -f -- "$file")
done
문제는 file
루프 내의 설정이 위치 인수 목록의 내용에 영향을 미치지 않는다는 것입니다.
대신에 다음을 사용하고 싶을 수도 있습니다.
for file in "$@"; do
[ -L "$file" ] && file=$(readlink -f -- "$file")
set -- "$@" "$file"
shift
done
이제 항목을 처음부터 하나씩 제거 "$@"
하고 잠재적으로 수정된 항목을 목록 뒤쪽에 추가하겠습니다. 루프 $@
내 for
수정은 루프가 항상 정적 목록을 반복하기 $@
때문에 문제가 되지 않습니다 for
. 즉, 반복된 목록은 루프 시작 시 한 번만 평가됩니다.
아래 루프와 마찬가지로 위 루프는 각 반복마다 위치 매개변수의 전체 목록을 재설정합니다. 하나를 위해거대한파일 이름 목록이 너무 빨리 느려질 수 있습니다. 쉘에 배열이 있는 경우,스티븐 키트의 답변작업 속도를 높이는 방법을 보여줍니다.
루프는 약간 더 짧은 형식( readlink
각 요소마다 호출됨)으로 작성할 수도 있습니다.
for dummy do
set -- "$@" "$(readlink -f -- "$1")"
shift
done
readlink
이것은 POSIX 유틸리티가 아니더라도 귀하의 질문에 따라 사용됩니다 .
참고로 출력된다면readlink
하나 이상의 줄 바꿈으로 끝납니다(출력의 마지막 줄을 종료하기 위해 추가된 내용을 제외하고) 제거됩니다. 이는 명령 대체의 결과입니다. 이것이 문제인 경우 명령 대체에 후행 문자를 인위적으로 추가하고 mosvy
제안된 대로 제거하십시오.댓글에서:
for file do
[ -L "$file" ] && file=$(readlink -f -- "$file"; echo x)
set -- "$@" "${file%x}"
shift
done
답변2
POSIX 명령 은 둘 다 및 readlink
가 아닙니다 . POSIX 명령줄 도구 상자에는 유사한 API가 realpath
없습니다 . 여기에서는 유사한 기능과 해당 수정자가 내장되어 있는 이를 realpath()
대신 사용할 수 있습니다 readlink
(호환되지 않는 다른 구현이 있음) . 스크립트 에서 :zsh
realpath()
:P
sh
eval "set -- $(zsh -c 'print -r ${(qq)argv:P}' zsh "$@")"
zsh
스크립트를 먼저 작성할 수도 있지만 다음과 같아야 합니다.
argv=($argv:P)
아니면 python3
zsh보다 더 유용합니까?
eval "set -- $(
LC_ALL=C python3 -c '
import sys, os, shlex
print(" ".join(map(shlex.quote, map(os.path.realpath, sys.argv[1:]))))' "$@")"