最も近い一致フォルダを探す

最も近い一致フォルダを探す

「/」の発生回数に基づいて結果をソートし、$ find . -name scripts -type d最初の結果を選択する最良の方法は何ですか?

cd私のプロジェクトのパブリックフォルダを指す関数を作成したいと思います。私はそれがあなたの相対ディレクトリに基づいて柔軟になりたいです。

したがって、フォルダ構造がすべて似ている10のプロジェクトがある場合:

~/project-a/project/folder/structure
~/project-b/project/folder/structure
~/project-c/project/folder/structure

私はできます:

$ cd ~/project-a
$ cdd structure

~/project-a/project/folder/struct に配置されます。

修正する

たとえば、次のように予測可能な方法で結果を並べ替えることはできません。

$ find . -type d -name "themes"

./wp-content/plugins/contact-form-7/includes/js/jquery-ui/themes
./wp-content/plugins/jetpack/modules/infinite-scroll/themes
./wp-content/plugins/smart-youtube/themes
./wp-content/plugins/wptouch-pro/themes
./wp-content/themes
./wp-includes/js/tinymce/themes

cdd関数が最も近い結果に降りたいのです。この例ではです./wp-content/themes

答え1

これにより、zsh次のことができます。

cdd() cd -- **/$1(/Od[1])

cdd themes

このcdd機能は、あらゆる種類のファイルを検索します。目次/)に引数として与えられた名前を使用してepthでソートし、$1最初の項目()を選択します。Od[1]

D非効率的な点は、現在のディレクトリに一致するディレクトリがある場合でも、ディレクトリツリー全体をクロールすることです(隠しディレクトリをスキップして変更するためにglob修飾子を追加します)。

一度に 1 つのレベルでディレクトリ ツリーをナビゲートするには、次の手順を実行します。

cdd() {
  local dirs matches
  dirs=(.)
  while (($#dirs)) {
    matches=($^dirs/$1(N/[1]))
    if (($#matches)) {
      cd $matches[1]
      return
    }
    dirs=($^dirs/*(/N))
  }
  print >&2 Not found
  return 1
}

答え2

エイリアスは途中でパラメータを受け入れることができず、最後にのみ許可されるため、この問題を解決するためにエイリアスを使用することはできません。これを達成するには機能が必要です。

次の機能がお客様の要件を満たすことができます。

cdd() { 
   cd `find . -type d -name "$1"|head -n1`
}

ログイン時にこの行が一度実行されるように、.profile(または.bashrcファイル)にこの行を追加する必要があります。

テストのためにこれをというファイルに入れてからインポートfunc.shすると(つまり、「.」演算子を使用して実行されます)、環境の一部になります。

. ./func.sh

注:ファイルを変更した場合は、func.shそのファイルを再インポートする必要があります。

その後、次のように使用できます。

cdd <dirname>

関数は<dirname>現在のパスとその名前を持つディレクトリの下を検索し、見つかったcd最初の一致(head -n1)を検索します。

find最初に目的の結果を得るためにタスクを細かく調整できます。望むよりman find

最も近い一致を見つけるには、find出力をソートして最短行を提供できます。

find . -type d -name "$1"| awk '{ print length, $0 }' | sort -n -s | cut -d" " -f2- | head -n1

(このawkコマンドは以下から盗まれました。ここ.)

これはfindの出力から最も短い行を返します。ただし、ディレクトリを探していますが、proj次のような構造がある場合は、無効なディレクトリが返されます。

./d1/d2/d3/proj
./longdirname/proj

または、結果の文字数を数えることで/この問題を解決できます。

答え3

findこのbash機能は、現在のディレクトリのすべてのディレクトリ階層に対して無差別代入クラッキングを実行し、指定されたディレクトリを検索します。

cdd() {
  if [ "$#" -ne 1 ]
  then
    printf '%s: Error: one directory name expected\n' "${FUNCNAME[0]}" >&2
    return
  fi

  maxdepth=$(find . -type d -exec sh -c 'printf %s "$1" | LC_ALL=C tr -dc / | wc -c' findshell {} \; | sort -n | tail -1)
  for((i=1; i <= maxdepth; i++))
  do
    dir=$(find . -mindepth "$i" -maxdepth "$i" -type d -name "$1")
    if [ -n "$dir" ]
    then
        command cd -- "$dir"
        return
    fi
  done
  printf '%s: %s: no such directory found\n' "${FUNCNAME[0]}" "$1" >&2
}

最初のfindコマンドは、現在のディレクトリの下の各ディレクトリに対してシェルフラグメントを実行します。シェルフラグメントはディレクトリ名をtr& wcpipe に印刷し、スラッシュ以外のすべての文字を削除し、スラッシュの数を数えます。私はこの技術をilkkachuおよびStéphane Chazelasから学びました。ここ。すべてのディレクトリの深さを出力したら、sort | tail最大数を見つけます。これは検索する必要がある最大ディレクトリ深さです。

findその後、現在のディレクトリから始まり、最も深いディレクトリまで順番に各ディレクトリの深さを制限するループです。一致するものが見つかったら、cd関数を終了します。一致するものがない場合は、ループを終了してstderrにメッセージを出力します。

答え4

bashの再帰ワイルドカード機能を使用することもできます。

shopt -s globstar  # in ~/.bashrc, or just in cdd() {}
cd **/structure/

**拡張はルックアップとほぼ同じ順序で発生するため、ほとんど同じ問題があると思います。しかし、あまりにもシンプルで便利なので見過ごすことができます!

複数のパラメータを持つ拒否のbash最新バージョンcdしたがって、これは一致する項目が1つしかない場合にのみ機能します。それ以外の場合は取得しますcd: too many arguments

したがって、シェル機能が必要です。array=( **/"$1"/ )空でない場合は最初の要素を使用できますが、関数を作成する場合はfind -depth -type d | tail -1最後の結果(最も浅い結果の1つ)を取得したい場合があります。または、-maxdepth木がかなり深いと思われる場合は、段階的に使用してください。

関連情報