스크립트에서 glob을 사용하여 하위 디렉터리가 있는지 확인

스크립트에서 glob을 사용하여 하위 디렉터리가 있는지 확인

bin가끔 변경되는 디렉토리 안에 디렉토리가 있는지 확인하려고합니다 . 이 특별한 경우에는 Ruby의 버전 번호가 변경될 수 있습니다(예 $HOME/.gem/ruby/2.6.0/bin: ). 지금까지 내가 한 일은 다음과 같습니다.

#!/usr/bin/env zsh
ruby_gem_home="$HOME/.gem/ruby/*/bin"
if [[ -d $ruby_gem_home ]]; then
  echo "The ruby gems directory exists!"
else
  echo "Ruby gems directory missing!"
fi

find이것은 로그인 프로세스의 일부이므로 사용하고 싶지 않습니다 . 내장된 zsh/bash 명령을 사용하여 이를 달성하는 가장 우아한 방법은 무엇입니까?

감사해요!

편집하다:이것이 스크립트라는 것을 잊어버렸습니다 zsh.

답변1

특히 이 상황에 대해

디렉토리를 찾는 데는 아무런 의미가 없다고 생각합니다. 설치된 Ruby 버전과 일치하지 않는 디렉토리를 사용하는 이유는 무엇입니까? 사용자가 에서 다른 디렉터리를 구성하면 어떻게 되나요 ~/.gemrc?

나는 Ruby에 익숙하지 않지만 올바른 해결책은 gempath.

ruby_gem_home=$(gem environment gempath | sed 's/:.*//')
if [ -z "$ruby_gem_home" ]; then unset ruby_gem_home; fi

zsh에서

function set_ruby_gem_home {
  emulate -LR zsh
  local dirs
  dirs=($HOME/.gem/ruby/*/bin(NnOn))
  if (($#dirs == 0)); then
    unset ruby_gem_home
  else
    ruby_gem_home=$dirs[0]
  fi
}

이것글로벌 예선 N불일치로 인해 오류가 발생하는 대신 결과가 빈 배열인지 확인하세요. glob 한정자를 사용 n하고 On버전 번호를 줄여 목록을 정렬합니다. 일치하는 항목이 여러 개인 경우 다른 항목을 선택하려면 이 옵션을 조정하세요.

배쉬에서:

function set_ruby_gem_home {
  local dirs
  dirs=(~/.gem/ruby/*/bin(NnOn))
  if (($#dirs == 0)); then
    unset ruby_gem_home
  else
    ruby_gem_home=$dirs[0]
  fi
}

배쉬에서

function set_ruby_gem_home {
  local dirs restore_options
  restore_options=$(setopt +o)
  shopt -s nullglob
  dirs=(~/.gem/ruby/*/bin)
  if (($#dirs == 0)); then
    unset ruby_gem_home
  else
    ruby_gem_home=${dirs[${#dirs[@]}-1]}
  fi
  eval "$restore_options"
}

여기서는 일반적으로 항상 최신 버전은 아니지만 마지막 배열 요소를 사용합니다. 10sorted before 9.

답변2

배열을 사용하여 배열의 첫 번째 요소(예: bash의 경우 [0], zsh의 경우 [1])가 디렉터리인지 확인하세요. 예를 들면 다음과 같습니다 bash.

# the trailing slash in "$HOME"/.gem/ruby/*/bin/ ensures that
# the glob matches only directories.
rubygemdirs=( "$HOME"/.gem/ruby/*/bin/ )

if [ -d "${rubygemdirs[0]}" ] ; then
   echo "At least one ruby gem dir exists"
else
   echo "No ruby gem dirs were found"
fi

zsh작업을 수행하려면 bash먼저 현재 실행 중인 쉘을 찾아야 합니다. 이는 배열의 첫 번째 인덱스가 0또는 인지 알려줍니다 1. 또한 (N)glob과 일치하는 항목이 없으면 zsh가 종료하지 않도록 glob과 함께 사용해야 하는지 여부도 결정합니다 (glob이 오류와 일치하면 zsh는 기본적으로 종료됩니다).

(이 시점에서 안정적으로 작동하는 스크립트를 작성하는 것이 분명해지기 시작해야 합니다.둘 다bash와 zsh는 아마도 가치 있는 것보다 더 많은 문제가 있을 것입니다)

if [ -n "$BASH_VERSION" ] ; then
   first_idx=0
   rubygemdirs=( "$HOME"/.gem/ruby/*/bin/ )
elif [ -n "$ZSH_VERSION"  ] ; then
   first_idx=1
   emulate sh
   rubygemdirs=( "$HOME"/.gem/ruby/*/bin/ )
   emulate zsh
fi

if [ -d "${rubygemdirs[$first_idx]}" ] ; then
...

필요한 경우 배열을 반복하여 요소가 특정 버전과 일치하는지 확인할 수도 있습니다. 예를 들어

for d in "${rubygemdirs[@]}" ; do
  [[ $d =~ /2\.6\.0/ ]] && echo found gem dir for ruby 2.6.0
done

참고: /정규 표현식의 s는 문자 그대로 슬래시입니다. 에서처럼 정규식의 시작과 끝을 표시하지 않습니다 sed.

답변3

와일드카드는 목록 컨텍스트에서만 확장됩니다. 즉, 여러 콘텐츠로 확장될 수 있습니다. 스칼라 변수에 할당할 경우 스칼라 변수는 하나의 값만 보유할 수 있으므로 확장할 수 없습니다.

를 사용하면 목록 컨텍스트에서 glob이 확장되는 파일 목록이 아닌 문자열을 스칼라 변수에 저장하기 ruby_gem_home="$HOME/.gem/ruby/*/bin"만 하면 됩니다 ./home/user/.gem/ruby/*/bin$ruby_gem_home

for/select x inzsh의 목록 컨텍스트는 리디렉션 대상( multios열릴 때), 배열 또는 연관 배열 할당 및 기타 일부 경우 에서 간단한 명령 또는 익명 함수에 대한 인수가 될 수 있습니다 .

여기서는 익명 함수를 사용할 수 있습니다.

() {
  unset ruby_gem_home
  case $# in
    (0) print -u2 "Ruby gems directory missing!";;
    (1) print -u2 "The ruby gems directory exists!"
        ruby_gem_home=$1;;
    (*) print -u2 "More than one ruby gem directory, don't know which to choose!";;
  esac
} ~/.gem/ruby/*/bin(N-/)

Nglob 한정자는 일치 항목이 없을 때 오류를 보고하는 대신 glob이 빈 목록으로 확장되고 -/파일 형식으로 제한되도록 여기에 추가됩니다.목차(심볼릭 링크 해결 후에 결정됨 -)

Ruby gem 디렉토리가 여러 개 있고 버전 번호가 가장 높은 디렉토리를 선택하려면 다음을 수행하세요.

() {
  unset ruby_gem_home
  case $# in
    (0) print -u2 "Ruby gems directory missing!";;
    (1) print -u2 "The ruby gems directory exists!"
        ruby_gem_home=$1;;
    (*) print -ru2 "More than one ruby gem directory, picking $1!"
        ruby_gem_home=$1;;
  esac
} ~/.gem/ruby/*/bin(N-/nOn)

ame 에 의해 역순 으로 열리고 정렬되므로 n가장 높은 숫자를 가진 것이 포함됩니다.numericglobsortOn on$1


1 설명된 대로info zsh 'Conditional Expressions', 특별한 경우도 있습니다. 이 extendedglob옵션이 켜져 있으면 [[ ... ]]일반적으로 -n/ -z연산자를 사용하여 내부적으로 glob을 사용할 수 있습니다. 따라서 [[ -n ~/.gem/ruby/*/bin(#qN-/) ]]여기에 그러한 디렉토리가 하나 이상 있는지 확인하는 데 사용할 수 있습니다 .

관련 정보