Linuxを探す-type d:./dir1なしで./dir1/dir2などの最も深いディレクトリを一覧表示する方法は?

Linuxを探す-type d:./dir1なしで./dir1/dir2などの最も深いディレクトリを一覧表示する方法は?
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-commandfnBourne-shellやほとんどのBourne様シェルと同様に、関数を本文として定義しますsome-command
  • () { code } argscode匿名関数は位置引数として実行されます。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 -rC1olumnに対応するパラメータrawを印刷します。1 C
  • ^+has_subdirshas_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}'
)

一部のシステムやファイルシステム(ext4Linuxベースのシステムなど)では、サブディレクトリがあるディレクトリのリンク数が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オプションが欲しいものです。

関連情報