フォルダリストがありますが、ほとんどのフォルダ名がどのフォルダ名で始まるかを知りたいです。
次のフォルダのリストが与えられたら:
./
./.something
./unrelated
./Target.Dire ctoryName
./Target.Dire ctoryNameOther
./Target.Dire ctoryName.Other
./Target.Dire ctoryName.Stuff
./Target.Dire ctoryName.Stuff.Other
./Unrelated.Dire ctoryName
./Unrelated.Dire ctoryNameStuff
./Unrelated.Dire ctoryName.Stuff
./Unrelated.Dire ctoryName.Other
./More.Unrelated.Dire ctoryName
./More.Unrelated.Dire ctoryName.Other
./Target.Dire ctoryName
名前(スペースを含む)を知りたいです。
私はこれを思い出しましたが、隠されたフォルダを除いて非常に長く、「次へ開始」を実行せずに「インクルード」を実行します。
find * -maxdepth 0 -type d | xargs -d $'\n' sh -c \
'for arg do find * -maxdepth 0 -type d | grep -wo "$arg"; done' _ \
| sort | uniq -c | sort -nr | head -1 | echo "./$(awk '{print $2}')"
隠しフォルダがあるバージョンとないバージョンの2つのバージョンがあります。マイユースケースでは、find * -maxdepth 0 -type d
すべての潜在的なフォルダが含まれています。
フォルダ名が必要な理由は、私が使用するツールが特定のパラメータで使用されているときに「target / home」ディレクトリを特定できないためです。
答え1
を使用すると、zsh
次のことができます。
all=(*(N/)) max=0 best=
for dir ($all) (){ (( $# > max )) && max=$# best=$dir; } ${(M)all:#$dir*}
print -r -- $max $best
*(N/)
タイプに拡張される非隠しファイル目次現在のディレクトリ(またはullglob修飾子と一致しない場合は何もありませんN
)。
${(M)all:#$dir*}
パターンに一致する配列要素に展開されます$all
。つまり、この値は匿名関数()に引数として渡され、最大値と比較されます。M
$dir*
$dir
(){....}
同じ状況が発生した場合は、語彙順にソートされたディレクトリのリストから最初のディレクトリを選択します(最後のディレクトリを取得するにはに>
置き換えます)。>=
隠しディレクトリを含めるには(常に除外するには)、glob修飾子()を追加しD
ます。dotglob
all=(*(ND/))
.
..
以下は元の答えです。要件をすばやく読みました。ディレクトリ自体の名前でなくても、そのディレクトリの最も一般的な共通プレフィックスを探します。たとえば、between、ab1
および代わりに次を返しab2
ab3
ます。bc
bc1
ab
bc
typeset -A c
for f (*(/)) for ((i=1;i<=$#f;i++)) ((c[\$f[1,i]]++))
printf -v argv '%2$08d%1$s' ${(kv)c}
print -r -- ${${(O)@}[1][9,-1]}
*(/)
タイプに拡張される非隠しファイル目次現在ディレクトリにあります(それ以外の場合はエラーで中断されます)。
次に、連想配列を構築して、$c
これらのディレクトリ名に対して可能な各プレフィックスの発生回数を記録します。
次に、発生数に基づいて配列を設定し、0から8桁まで入力し、$argv
各プレフィックスにプレフィックスを追加します。$@
その後、O
その配列を語彙の逆順に並べ替えるので、最初の配列が最も頻繁に発生する配列になり、同率があれば最後の配列が整列されます(最も長いプレフィックスも提供されます)。
次に、最初の文字()を選択し、[1]
最後の9番目の文字()を印刷します。[9,-1]
隠しディレクトリを含めるには(修飾子に追加)*(/)
に置き換えます。含まれていません。*(D/)
D
dotglob
.
..
答え2
純粋なbashでこれを行う方法はよくわかりませんが、以下のPythonスクリプトはすべての可能なフォルダ名に対して機能するはずです。また、コマンドライン引数も受け入れます(後述)。オプションのパターン一致パラメータ)。
#!/usr/bin/env python3
import subprocess
import sys
if len(sys.argv) == 1:
folder = subprocess.run(\
['find','-mindepth','1','-maxdepth','1','-type','d','-print0'],\
capture_output=True).stdout[:-1].split(b'\x00')
else:
folder = subprocess.run(\
['find','-mindepth','1','-maxdepth','1','-type','d',\
'-name',sys.argv[1], '-print0'],\
capture_output=True).stdout[:-1].split(b'\x00')
counts = []
for name in folder:
counts.append(sum(name in i[:len(name)] for i in folder))
counts = sorted(list(zip(counts,folder)),reverse=True)
if counts[0][0]>1:
sys.stdout.buffer.write(counts[0][1]+b'\x0a')
スクリプトをmainfoldername.py
別の名前で保存すると、コマンドはpython3 /path/to/mainfoldername.py
現在の作業ディレクトリからフォルダ名の開始文字列として最も頻繁に発生する基準を満たすフォルダ名を出力します。この条件を満たすフォルダがない場合、スクリプトは出力を生成しません。
提供されたディレクトリの例を使用すると、python3 /path/to/mainfoldername.py
出力は次のようになります。./Target.Dire ctoryName
。
使用コマンド拡張、変数はスクリプトの出力値に設定され、他のコマンドで使用できます。
$ myvar="$( python3 /path/to/mainfoldername.py )"
$ echo "$myvar"
./Target.Dire ctoryName
$ cd "$myvar"
Target.Dire ctoryName$
シェルスクリプトの使用
存在するシェルスクリプトこの出力が使用され、基準を満たすフォルダ名がない場合(たとえば、Pythonスクリプトが出力を生成しない場合)、長さ0の値をテストして確認する必要があります。例:
#!/bin/sh
myvar="$( python3 /path/to/mainfoldername.py )"
[ ! -z "$myvar" ] || exit 1
オプションのパターン一致パラメータ
python3 /path/to/mainfolder.py PATTERN
スクリプトはコマンドラインでオプションの引数を受け入れます。PATTERN
フォルダ名が一致する必要があるシェルパターン。
最も基本的な用途は、通常のフォルダの検索と隠しフォルダの検索を切り替えることです。このスクリプトのデフォルトの動作は、すべてのフォルダを見つけることです。
隠しフォルダのみを探す、使用'.*'
~のためPATTERN
:
python3 /path/to/mainfolder.py '.*'
隠されていないフォルダのみを探す、使用'[!\.]*'
python3 /path/to/mainfolder.py '[!\.]*'
ターゲットフォルダ名に表示される特定の文字列を知っている場合にも便利です。
名前にこの文字列を含むフォルダのみを探すTarget
:
python3 /path/to/mainfolder.py '*Target*'
シェルによる拡張を防ぐには、パターンを常に引用符で囲む必要があります。バラより「シェルパターンマッチング」より多くの情報を知りたいです。
答え3
次のawk
プログラムは、最も頻繁に発生するディレクトリパスを、入力内のすべてのディレクトリパスの接頭辞として出力します。
ディレクトリパスは一度に1行ずつ表示され、パス名に改行文字が含まれていないと仮定します。
{ sub("/$",""); count[$0] = 0 }
END {
for (p1 in count)
for (p2 in count) {
count[p2] += (index(p1,p2) == 1)
if (count[p2] > m) {
m = count[p2]
p = p2
}
}
print p
}
これは入力の各行を読み取り、それを連想配列のキーとして保存しますcount
。/
まず、末尾を削除します。
すべての入力を読み取ったら、保存されたキーをペアで比較し、各キーが別のキー内の部分文字列として表示される回数を計算します。で最も頻繁に発生するパス名p
とで発生した回数を追跡しますm
。
この呼び出しは、index(p1,p2)
文字列で発生が発生した場所p1
(p2
または発生がまったくない場合は0)を返し、結果が数字1(p2
最初から発生p1
)の場合にのみ興味があります。
上記のプログラムは、次のようにコマンドラインからインラインで作成することもできます。
awk '{ sub("/$",""); c[$0]=0 } END { for (a in c) for (b in c) { c[b]+=(index(a,b)==1); if (c[b]>m) { m=c[b]; p=b } } print p }'
これへの入力として、以下を使用できます。
printf '%s\n' ./*/
(シェルdotglob
で有効にすると、隠しディレクトリ名を取得することもできます。)bash
結局のところ、あなたは次のようなものを得るでしょう
shopt -s dotglob
printf '%s\n' ./*/ | awk -f script
awk
(または代わりに、より長いインラインスクリプトを使用してください-f script
。)
テスト:
$ ls -FA
.something/ Unrelated.Dire ctoryName/
Target.Dire ctoryName/ Unrelated.Dire ctoryName.Other/
Target.Dire ctoryName.Other/ Unrelated.Dire ctoryName.Stuff/
Target.Dire ctoryName.Stuff/ Unrelated.Dire ctoryNameStuff/
Target.Dire ctoryName.Stuff.Other/ script
Target.Dire ctoryNameOther/ unrelated/
$ shopt -s dotglob
$ printf '%s\n' ./*/ | awk -f script
./Target.Dire ctoryName
答え4
C#スクリプト
これはC#スクリプト:
#!/usr/bin/env dotnet-script
var dirs = Directory.GetDirectories(".");
Console.Write(dirs.MaxBy(d => dirs.Count(x => x.StartsWith(d))));
ディレクトリからを実行しますdotnet script /path/to/mainfoldername.csx
。