다른 HPC 노드, VM 또는 개인 워크 스테이션에서 다른 버전의 Bash를 실행할 수있는 비교적 이기종 환경에서 작업합니다. 로그인 스크립트를 Git 리포지토리에 넣었 기 때문에 .bashrc
“이 호스트라면 …”형식의 혼잡함없이 보드 전체에서 동일한 (ish) 을 사용하고 싶습니다 .
나는 같은 배쉬 ≤ 확장 4.1의 기본 동작 cd $SOMEPATH
에 cd /the/actual/path
가압 할 때 Tab키를 누릅니다. 배쉬 4.2 이상, 당신이해야 shopt -s direxpand
하는이 동작을 다시 설정하고, 그 사용할 수있게하지 않았다 4.2.29까지 . 그러나 이것은 하나의 예일뿐입니다. 또 다른 관련 shopt
옵션은 complete_fullquote
(내가 정확히 무엇인지 모르지만 ) v4.2의 기본 동작을 변경했을 수도 있습니다.
그러나 direxpand
이전 버전의 Bash에서는 인식하지 못하며 shopt -s direxpand
my에서 시도 .bashrc
하면 이전 Bash가있는 노드에 로그인 할 때마다 오류 메시지가 콘솔에 인쇄됩니다.
-bash: shopt: direxpand: invalid shell option name
내가하고 싶은 것은 shop -s direxpand
이전 버전의 Bash를 손상시키지 않고 ( 즉 , 오류 출력을로 리디렉션하는 것이 아니라) Bash> 4.1에서 해당 옵션을 강력한 방법으로 사용하도록 조건부를 감싸는 것 /dev/null
입니다.
답변
direxpand
출력에 있는지 확인하고 다음 과 같은 경우 shopt
활성화하십시오.
shopt | grep -q '^direxpand\b' && shopt -s direxpand
답변
에 오류를 리디렉션하는 데 무엇이 문제인지 알 수 없습니다 /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
성능면에서 이길 수는 없다고 생각합니다.
답변
Bash의 특정 메이저 / 마이너 / 패치 릴리스에서 특정 shopt
옵션 을 사용할 수 있음을 확실히 알고 있으면 조건부로 $BASH_VERSION
변수 $BASH_VERSINFO[]
를 활성화하기 위해 변수 또는 배열 요소를 검사 할 수 있습니다 .
다음 은 4.2 시리즈 direxpand
에 처음 도입 된 버전 인 Bash 4.2.29 이상에 대한 테스트입니다 .
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
편집 : 분명히, 이것은 단순히 로그인 스크립트에서 오는 오류 메시지를 무시하는 엄청나게 과장된 솔루션이지만, 내 자신의 교화를 위해 관계없이 문서화하고 싶었습니다.
주위에 괄호 주 , 하는 요구, 그리고 사용 및 (로케일에 따라 다름) 어휘의 비교보다는 정수 수행합니다. 인용되지 않은 경우, 운영자 의 RHS 는 여기 에 명시된 바와 같이 Bash / 조건부 내에서 “외부로”패턴으로 취급 되는데, 이는 정규식 IMO보다 더 미학적 “시작으로”비교합니다.${BASH_VERSINFO[index]}
-eq
-gt
==
[[
]]
$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
되는 배쉬 버전 (들) 지원 또는 그들의 행동을 변화되었고, 루치아노에 의해 제안 된 방법은 괜찮 :
# 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 , 3
관련 읽기 : 세트 및 쇼핑-왜 2입니까?