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"
}
ここでは通常、常に最新バージョンではありませんが、最後の配列要素を使用します。10
sorted 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
ワイルドカードはリストコンテキストでのみ拡張されます。つまり、複数のコンテンツに拡張できます。スカラー変数に割り当てると、スカラー変数は1つの値しか保持できないため、拡張できません。
を使用すると、リストコンテキストでglobが拡張されているファイルリストではなく、文字列をスカラー変数に保存するだけですruby_gem_home="$HOME/.gem/ruby/*/bin"
。/home/user/.gem/ruby/*/bin
$ruby_gem_home
for/select x in
zshのリストコンテキストは、リダイレクトターゲット(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-/)
N
glob修飾子は、一致がない場合にエラーを報告するのではなく、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
最も高い数値を持つものが含まれます。numericglobsort
On
o
n
$1
1 説明のとおりinfo zsh 'Conditional Expressions'
、特別な場合もあります。このextendedglob
オプションがオンの場合、[[ ... ]]
通常は-n
/-z
演算子を使用して内部でglobを使用できます。したがって、[[ -n ~/.gem/ruby/*/bin(#qN-/) ]]
ここでそのようなディレクトリが1つ以上あることを確認するために使用できます。