POSIX 쉘 스크립트에서 $@ 배열을 수정하는 방법이 있습니까?

POSIX 쉘 스크립트에서 $@ 배열을 수정하는 방법이 있습니까?

readlinkSymLinks에서 일반 파일을 가져오는 방법을 알고 있을 수도 있습니다 . 나는 $@다음과 같이 내 함수에 전달된 SymLink를 대체하는 매우 기본적인 아이디어를 가지고 있었습니다 .

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

readlinkPOSIX 유틸리티는 아니지만 귀하의 질문에 따라 사용됩니다 .

출력되는 경우readlink 하나 또는 여러 줄 바꿈으로 끝납니다(출력의 마지막 줄을 종료하기 위해 추가된 것 외에), 이것들은 제거됩니다. 이는 명령 대체의 결과입니다. 이것이 문제인 경우 다음과 같이 명령 대체에 인위적으로 후행 문자를 추가한 다음 제거하십시오.mosvy 제안된 대로 제거하십시오.댓글에서:

for file do
    [ -L "$file" ] && file=$(readlink -f -- "$file"; echo x)
    set -- "$@" "${file%x}"
    shift
done

답변2

POSIX 명령 readlink도 마찬가지 입니다. realpathPOSIX 명령줄 도구 상자에는 realpath()-like API가 없습니다. 여기서는 (다른 호환되지 않는 구현이 있음) 대신 해당 수정자와 함께 -like 기능이 내장되어 있는 것을 readlink사용할 수 있습니다 . 스크립트 에서 :zshrealpath():Psh

eval "set -- $(zsh -c 'print -r ${(qq)argv:P}' zsh "$@")"

zsh처음부터 다음과 같이 스크립트를 작성할 수도 있습니다 .

argv=($argv:P)

또는 python3zsh보다 사용할 가능성이 더 높은 경우:

eval "set -- $(
  LC_ALL=C python3 -c '
import sys, os, shlex
print(" ".join(map(shlex.quote, map(os.path.realpath, sys.argv[1:]))))' "$@")"

관련 정보