「/」の発生回数に基づいて結果をソートし、$ 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
最初の項目()を選択します。O
d
[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
& wc
pipe に印刷し、スラッシュ以外のすべての文字を削除し、スラッシュの数を数えます。私はこの技術を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
木がかなり深いと思われる場合は、段階的に使用してください。