shellcheck에서는 basename 사용을 권장하지 않습니다. 이유는 무엇입니까?

shellcheck에서는 basename 사용을 권장하지 않습니다. 이유는 무엇입니까?

나는 노력하고있다주택 검사.

나는 다음과 같은 것을 가지고 있습니다

basename "${OPENSSL}" 

나는 다음과 같은 조언을 얻었다

Use parameter expansion instead, such as ${var##*/}.

실용적인 측면에서는 별 차이가 없다고 생각합니다.

$ export OPENSSL=/opt/local/bin/openssl
$ basename ${OPENSSL}
openssl
$ echo ${OPENSSL##*/}
openssl

basename에 있기 때문에POSIX 사양, 왜 이것이 모범 사례가 되어야 하는지 모르겠습니다. 어떤 팁이 있나요?

답변1

효율성에 관한 것이 아니라 정확성에 관한 것입니다. basename인쇄되는 파일 이름을 구분하려면 개행 문자를 사용하세요. 일반적인 경우 파일 이름만 전달하면 출력에 줄바꿈 문자가 추가됩니다. 파일 이름 자체에 개행 문자가 포함될 수 있으므로 이러한 파일 이름을 올바르게 처리하기가 어렵습니다.

basename사람들이 일반적으로 다음과 같이 사용한다는 사실로 인해 상황은 더욱 복잡해집니다 "$(basename "$file")". 이로 $(command)인해 상황이 더욱 어려워집니다 .모두후행 개행 문자는 에서 나옵니다 command. $file개행 문자로 끝나는 가능성이 낮은 경우를 생각해 보세요. 그런 다음 basename추가 줄 바꿈이 추가되지만 "$(basename "$file")"제거됩니다.둘 다줄 바꿈으로 인해 잘못된 파일 이름이 남습니다.

또 다른 문제는 (대시, 일명 빼기 기호)로 시작 basename하면 옵션으로 해석된다는 것입니다. 이 문제는 해결하기 쉽습니다.$file-$(basename -- "$file")

강력한 사용법은 basename다음과 같습니다.

# A file with three trailing newlines.
file=$'/tmp/evil\n\n\n'

# Add an 'x' so we can tell where $file's newlines end and basename's begin.
file_x="$(basename -- "$file"; printf x)"

# Strip off two trailing characters: the 'x' added by us and the newline added by basename. 
base="${file_x%??}"

또 다른 방법은 을 사용하는 것인데 ${file##*/}, 이 방법은 더 간단하지만 자체적인 버그도 있습니다. 특히 $fileis 또는 /의 경우에는 틀립니다 foo/.

답변2

shellcheck관련 라인소스 코드예:

checkNeedlessCommands (T_SimpleCommand id _ (w:_)) | w `isCommand` "dirname" =
    style id "Use parameter expansion instead, such as ${var%/*}."
checkNeedlessCommands (T_SimpleCommand id _ (w:_)) | w `isCommand` "basename" =
    style id "Use parameter expansion instead, such as ${var##*/}."
checkNeedlessCommands _ = return ()

명시적인 설명은 없지만 함수 이름( checkNeedlessCommands)을 보면 @jordanm이 새 프로세스를 포크하지 말라고 권고한 것이 꽤 맞는 것 같습니다.

답변3

dirnamebasename등 ( readlink@Marco 덕분에 수정되었습니다.) 보안이 중요해지면(경로 안전이 필요함) 이식성 문제가 발생할 수 있습니다. Fedora Linux와 같은 많은 시스템 /bin에서는 /usr/bincygwin, msys 등과 같은 Windows에 Bash가 있습니다. 가능하다면 순수한 Bash를 유지하는 것이 항상 더 좋습니다.(@Marco 댓글 기준)

그런데, shellcheck에 대한 포인터를 알려주셔서 감사합니다. 이전에는 본 적이 없습니다.

관련 정보