저는 서로 다른 HPC 노드, 가상 머신 또는 개인 워크스테이션에서 서로 다른 버전의 Bash를 실행할 수 있는 상대적으로 이질적인 환경에서 일하고 있습니다. 로그인 스크립트를 Git 저장소에 넣었기 때문에 .bashrc
"이 호스트라면..."과 같은 유형의 혼란 없이 전반적으로 동일한 스크립트를 사용하고 싶었습니다 .
나좋다Bash 4.1 이하의 기본 동작은 키를 누를 때의 동작 cd $SOMEPATH
으로 확장되었습니다. Bash 4.2 이상에서는 이 동작을 다시 활성화해야 합니다.cd /the/actual/path
Tabshopt -s direxpand
저것없는2029년 2월 4일까지. 하지만 이는 단지 예일 뿐이며 관련성이 있을 수 있는 또 다른 shopt
옵션 complete_fullquote
입니다 .정확히그 효과)는 v4.2의 기본 동작을 변경할 수도 있습니다.
그러나 direxpand
이전 버전의 Bash는 인식되지 않으며 shopt -s direxpand
내 에서 이 작업을 시도 하면 .bashrc
이전 버전의 Bash를 사용하여 노드에 로그인할 때마다 콘솔에 오류 메시지가 인쇄됩니다.
-bash: shopt: direxpand: invalid shell option name
내가 하고 싶은 것은 shop -s direxpand
이전 버전의 Bash에 영향을 주지 않고 강력한 방식으로 Bash > 4.1에서 옵션을 활성화하는 조건을 래핑하는 것입니다(즉, 오류 출력을 )로 리디렉션하는 것이 아닙니다 /dev/null
.
답변1
오류를 로 리디렉션하는 것을 이해할 수 없습니다 /dev/null
. 코드를 강력하게 만들려면 set -e
다음과 같은 일반적인 관용구를 사용하세요 … || true
.
shopt -s direxpand 2>/dev/null || true
옵션이 없을 때 일부 대체 코드를 실행하려면 다음 반환 상태를 사용하세요 shopt
.
if shopt -s direxpand 2>/dev/null; then
… # the direxpand option exists
else
… # the direxpand option does not exist
fi
그러나 리디렉션 오류가 정말 마음에 들지 않으면 완료 메커니즘을 사용하여 자체 검사를 수행할 수 있습니다. 이는 bash 2.03 이하이고 프로그래밍 가능한 완료 기능이 없는 오래된 시스템이 없다고 가정합니다.
shopt_exists () {
compgen -A shopt -X \!"$1" "$1" >/dev/null
}
if shopt_exists direxpand; then
shopt -s direxpand
fi
이 방법은 일부 환경(예: Cygwin)에서 속도가 느린 분기를 방지합니다. 단순하기 때문에 2>/dev/null
성능 면에서는 이길 수 없다고 생각합니다.
답변2
direxpand
출력에 존재하는지 확인 shopt
하고 존재하는 경우 활성화하십시오.
shopt | grep -q '^direxpand\b' && shopt -s direxpand
답변3
특정인을 식별할 때shopt
옵션Bash의 일부 주/부/패치 버전에서 사용할 수 있으며 $BASH_VERSION
변수 또는 배열의 요소를 확인하여 $BASH_VERSINFO[]
조건부로 활성화할 수 있습니다.
이것은 Bash 4.2.29 이상에 대한 테스트입니다.direxpand
처음 소개된4.2 시리즈의 경우:
if [[ $BASH_VERSION == 4.2.* && ${BASH_VERSINFO[2]} -ge 29 ]] ||
[[ ${BASH_VERSINFO[0]} -eq 4 && ${BASH_VERSINFO[1]} -ge 3 ]] ||
[[ ${BASH_VERSINFO[0]} -ge 5 ]]; then
shopt -s direxpand
fi
편집하다:분명히 말하면 이것은 로그인 스크립트의 오류 메시지를 단순히 무시하기 위한 과도한 엔지니어링 솔루션이지만, 어쨌든 내 참조를 위해 기록하고 싶었습니다.
주변 중괄호에 주목하세요.${BASH_VERSINFO[index]}
예(로케일에 따른) 어휘 비교 대신 정수를 수행하는 -eq
and 사용도 필요합니다 . -gt
인용되지 않은 경우 연산자의 RHS는 언급된 대로 Bash / 조건 에서 "extglob" 패턴 ==
으로 처리됩니다 .[[
]]
여기, 이는 정규식 IMO보다 더 아름다운 "시작" 비교를 제공합니다.
이것$BASH_VERSINFO
대량으로다음 출력에 표시되는 모든 정보가 포함되어 있습니다 bash --version
.
bash --version | head -1
# result:
# GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
declare -p BASH_VERSINFO
# result:
# declare -ar BASH_VERSINFO='([0]="4" [1]="3" [2]="48" [3]="1" [4]="release" [5]="x86_64-pc-linux-gnu")'
언제아니요shopt
Luciano가 제안한 접근 방식이 좋다는 Bash 버전이 지원되거나 동작이 변경된 문서에서 분명합니다 .
# note the '-q' so that the matched pattern isn't actually printed
shopt | grep -q direxpand && shopt -s direxpand
...Gilles가 제안한 솔루션처럼 오류( )를 무시 하고 꼭 필요한지 shopt -s direxpand 2>/dev/null
확인해보세요 .$?
인용하다:1,2,삼
관련 독서:정장과 쇼핑, 왜 둘일까요?