2017-12-09 3 views
0

入力したプロジェクト名とauto cdを含むgitプロジェクトを探したいとします。それは単純なbash関数であるべきですが、それは不思議な動作です。 forループ内の文がすべての値をtrueとして出力する場合 - bash

project() { 
    target=$1"/.git" 
    for string in "$(find ~ -name .git -type d -prune)" 
    do 
     if [[ $string == *"${target}" ]] 
     then 
      echo $string 
     else 
      echo 2 
     fi 
    done 
    # cd "$HOME/Work/$1/src" 
} 

私が見つけたすべてのプロジェクト(文字列値)をエコーし​​た場合、それは適切なプロジェクトのすべてを出力します。また、targetも有効な文字列です。期待される結果は、正しいパスが1回エコーされ、他のすべての値が2になるはずです。 targetstringの一部として一致すると問題が発生します。その場合は、必要なものではなく、すべてのプロジェクトを出力します。パターンがプロジェクトと一致しない場合、コードは2 ONCEの値を出力します。たぶん、私がzshを使っているという事実と関係しているかもしれませんが、私は本当に分かりません。

+5

あなたの引用符は、文字列があなたのパターンに一致するので、もしfind' 'の全体の結果は、単一の文字列で作っています全体が印刷されます。 'find'コマンドの一部として文字列のマッチングを行わない理由はありますか?また、マッチしないものも本当に必要ですか?単語の分割は、あなたがそれをやっているやり方でファイルを処理しようとするとあなたのために多くの問題を引き起こすでしょう –

答えて

3

ここにいくつかの問題があります。

  • シェルが二重引用符で囲まれた式に単語分割を行いませんので、ループ文脈で"$(find ...)"は、あなたがそれらを削除しても、単一の単語
  • ですが、二重引用符は、findの結果は、単語分割の対象となり、それはそれがより良いだろう、それは適切ではないfindの結果にパターンに一致するように[[ ... == ... ]]を使用しての
  • 代わりforループ内で使用することができますfindそのものを使用してパターンを一致させてください。それはツールが設計したものです
  • なぜecho 2、なぜechoがループしますか?この関数の結果をcdと使いたいと思われますが、それは複数の出力ではうまくいかないでしょう
  • 最後に、これはちょっとニックルですが、ここでの引用は問題ではありませんが、それは変です:target=$1"/.git"。あなたは実際にここで引用符を必要としません、これはうまくいくでしょう:target=$1/.git。コマンドライン引数に$1/.gitを使用していた場合は、.gitには特別な文字は含まれていないので、最も重要なのは$1です。長い話が短いので、"$1"/.gitまたは"$1/.git"と書いてください。

ここでは上記の問題を解決する一つの方法です:

project() { 
    local path 
    while IFS= read -rd '' path; do 
     echo "$path" 
     return 0 
    done < <(find ~ -type d -path "**/$1/.git" -print0) 
    echo "project not found: $1" >&2 
    return 1 
} 
+0

あなたはいくつかの改善を気にしないことを願っています。以前のバージョンでは、常にエラーメッセージが出力されます。 'find |からの切り替え'while(while)'はループが 'return'を許すサブシェルを削除します。 'IFS ='と '-print0'は本当に奇妙なファイル名の存在下でもコードをより安全にします。 –

0

あなたはこの関数はCDPATH変数を使用しないものの多くを行うことができます。例えば、

$ CDPATH=$HOME/Work 
$ cd project/src 
$ pwd 
/home/jyslar/Work/project/src 

はあなたの関数にこれを取り入れ、

project() { 
    local CDPATH="$HOME/Work" 
    cd "$1/src" 
} 

あり.gitディレクトリの明示的なチェックはありませんが、$HOME/Workの内容は、すべてGitリポジトリであると仮定するのが妥当と思われる、または(例えば、$HOME/Work/$1/srcが実際にGitリポジトリである$1のないディレクトリである場合)、偽陽性を避けるために少なくともprojectの定義を複雑にする価値はないということです。


質問:私にはCDPATHが必要ですか?ちょうど定義できませんでした

project() { cd "$HOME/Work/$1/src"; } 

はい、できます。私の主張は、あなたには機能が必要ではないということでした。追加するだけで

CDPATH=$HOME/Work 

.bashrcに追加してください。現在の作業ディレクトリにproject-omegaが存在しない場合、cd project-omega/srcは自動的に$HOME/Work/project-omega/srcになります。 PATH同様

CDPATHは、例えば、ディレクトリをコロンで区切ったリストを含めることができます。

CDPATH=$HOME/Work:$HOME/Fun:$HOME/Experimental 
+0

私はこれまでのような設定をしていましたが、サブモジュールを持つ複雑なプロジェクトのために、私はもう少しエレガントなもの – jsylar

関連する問題