find . -type d
通常表示されます。
./dir1
./dir1/dir2
./dir3
./dir3/dir4
./dir3/dir4/dir5
...
私はほしいだけです。
./dir1/dir2
./dir3/dir4/dir5
、親./dir1、...はありません。
つまり、サブディレクトリがないディレクトリだけを見たいのです。
どんなアイデアがありますか?
-links 2
編集:一般的なLinux環境で動作することがわかりました。
docker run -it --rm ubuntu:bionic find /etc -type d -links 2
完璧に動作します。
ただし、ディレクトリ(MacOSまたはWindows)をDockerコンテナにマウントすると、状況は変わり、機能しません。次のことを試すことができます。
docker run -it --rm -v /etc:/etc_of_host ubuntu:bionic find /etc_of_host -type d -links 2
答え1
そしてzsh
:
has_subdirs() () (( $# )) ${1-$REPLY}/*(ND/Y1)
print -rC1 -- **/*(ND/^+has_subdirs)
または仲介機能なしで直接:
print -rC1 -- **/*(ND/^e['()(($#)) $REPLY/*(ND/Y1)'])
それは:
fn() some-command
fn
Bourne-shellやほとんどのBourne様シェルと同様に、関数を本文として定義しますsome-command
。() { code } args
code
匿名関数は位置引数として実行されます。args
(( $# ))
ここで、匿名関数の本文は、以下を解決する算術式です。本物$#
(パラメータ数)が0以外の場合。${param-default}
(Bourneシェルでは)$param
引数が設定されているかdefault
どうかに拡張されます。ここでは、${1-$REPLY}
関数を直接呼び出すことがhas_subdirs mydir
できます(たとえば)、次のようにグローバル修飾子関数として呼び出すことができます。$dir/*(ND/Y1)
$dir
/
隠しファイル(otglob)を含む()のディレクトリタイプのファイルに展開し、D
一致するものがないと(ullglob)N
エラーを発生させません。しかし、その場合、Y1
最初のゲームで停止しました。したがって、has_subdirs
匿名関数は、ディレクトリに少なくとも1つのサブディレクトリが含まれている場合はtrueを返します。print -rC1
olumnに対応するパラメータr
awを印刷します。1
C
^+has_subdirs
has_subdirs
この関数はtrueを返さない()ファイルにのみ適用されます^
。
bash
シェルを使用する必要がある場合は、次のようにします。
zsh << 'EOF'
print -rC1 -- **/*(ND/^e['()(($#)) $REPLY/*(ND/Y1)'])
EOF
または、結果をbash配列に保存します(bash-4.4+が必要です)。
readarray -td '' array < <(zsh << 'EOF'
print -rNC1 -- **/*(ND/^e['()(($#)) $REPLY/*(ND/Y1)'])
EOF
)
(任意のパスを保存できるようにするには、NUL で区切られたレコードを使用します.)
そうでない場合は、zsh
次のperl
ことができます。
find . -depth -type d -print0 |
perl -l -0ne 'print if rindex $prev, "$_/", 0; $prev = $_'
またはGNUがある場合awk
:
find . -depth -type d -print0 |
gawk -v 'RS=\0' 'index(prev, $0"/") != 1; {prev = $0}'
find
印刷された目次深さ優先(該当するブランチの前に出る)見つからないレコードをインポートまたは印刷してから、以前のperl
レコードの先頭に表示します。awk
/
-l
同様に、bash 4.4+配列にファイルを保存するには、次に進むか、次を追加して-0
出力からNULで区切られたレコードに切り替える必要があります。perl
-v 'ORS=\0'
gawk
readarray -td array < <(
find . -depth -type d -print0 |
perl -0lne 'print if rindex $prev, "$_/", 0; $prev = $_'
)
readarray -td array < <(
find . -depth -type d -print0 |
gawk -v 'RS=\0' -v 'ORS=\0' 'index(prev, $0"/") != 1; {prev = $0}'
)
一部のシステムやファイルシステム(ext4
Linuxベースのシステムなど)では、サブディレクトリがあるディレクトリのリンク数が2より大きいことを信頼できます(およびdir
それぞれdir/.
への追加リンクdir/subdir/..
)。
print -rC1 -- **/*(ND/l-3)
find
または、すべてのシェルで使用してください。
find . -type d -links -3
ディレクトリのリンク数が常に1 btrfs
(複数のLinuxディストリビューションからデフォルトのファイルシステムに置き換えられている)の場合は機能しないため、通常のソリューションとしてはお勧めできません。ext4
Unionファイルシステムはあなたの場合と同じです。たとえば、overlayfs
一部を見つけました。マージディレクトリにはサブディレクトリが含まれているかどうかに関係なく、リンク数は1つです。
ただし、可能であれば、ディレクトリへの読み取りアクセスを必要としないサブディレクトリを手動で計算するソリューションに比べて利点があります(親ディレクトリへの検索アクセスのみが可能です)。
答え2
あなたが探しているもの:
find . -type d -links 2
ファイルシステムのすべてのディレクトリには、少なくとも2つのハードリンク(親ディレクトリのディレクトリ自体と「.」エントリ)があります。サブディレクトリの各「..」エントリは、ディレクトリに新しいハードリンクを追加します。したがって、2つのハードリンクがあるディレクトリを見つけるだけです。
他の回答で提案されたコマンド
find . -type d -links -3
同じことを行いますが、「ハードリンクされたディレクトリが3つ未満」と指定します。
答え3
最もソートされたアイテム:
p="";(find . -type d;echo) | while read d; do [[ $p && $d != $p/* ]] && echo $p; p=$d; done
連続して
a="";(find . -type d;echo )|while read i; do if [[ (! $i =~ $a) && ("$a" != "") ]]; then echo $a; fi; a=$i;done
OPで述べたように:
a="";(find . -type d;echo )|while read i; do [[ $i != $a/* && ! -z "$a" ]] && echo $a; a=$i;done
答え4
読むman find
。この-mindepth
オプションが欲しいものです。