次のディレクトリ構造と所有権を使用します。
userA ./dir1
userA ./dir1/dir1.1
userA ./dir1/dir1.2
userA ./dir2
userA ./dir2/dir2.1
userA ./dir2/dir2.1/dir2.1.1
userB ./dir2/dir2.2
userB ./dir3
実行すると、find . -type d -user userA
以下が返されます。
./dir1
./dir1/dir1.1
./dir1/dir1.2
./dir2
./dir2/dir2.1
./dir2/dir2.1/dir2.1.1
しかし、私はこの出力を見たいです。
./dir1
./dir2/dir2.1
dir1.1
dir1.2
他のユーザーがそれを所有していないため、返されませんdir1
。- 同様に
dir2.1.1
返品もありません。 dir2
userBに属しているため(userAに属していても)返されませんdir2.2
。
これは、ユーザーが実行するために「安全な」ディレクトリを識別できるようにディスクをクリーンアップするのに役立ちますrm -rf
。何十億ものファイルがある場合、du
ランタイムは非常に高いです。また、ディレクトリがすべての階層レベルにある可能性があるため、検索の深さを制限することは役に立ちません。
答え1
次のスクリプトを使用してください。
#!/bin/sh -
u="$1"
shift
find "$@" -type d -user "$u" ! -exec sh -c '
find "$2" -type d ! -user "$1" | grep -qm 1 .
' find-sh "$u" {} \; -prune -print
使用例:
/path/to/the_script userA ./
最初のパラメータ(ここではuserA
)はユーザー名です。以下のすべて(ここ./
)はに渡されますfind
。開始経路はこの方法で渡す必要があります(技術的には注入は可能ですが)。
スクリプトはmainを使用して、find
ユーザーが所有するディレクトリを見つけます。これらのディレクトリの場合、find
ユーザーに属さないサブディレクトリを探す他のディレクトリが呼び出されます。そうでない場合は、ディレクトリを削除し(したがってmainはfind
子ディレクトリを解決しません)、そのパス名を印刷します。
メモ:
- 内部的に
find
何かが見つかると、外部(デフォルト)find
はディレクトリをクリーンアップせずに代わりにサブディレクトリをチェックします。内部で見つかった内容が深い場合は、find
スクリプトがディレクトリツリーの別のブランチに移動する前に、さまざまなレベルの多くのサブディレクトリを何度も「無駄に」チェックします。ディレクトリツリーが非常に大きくない限り、オペレーティングシステムはメタデータをキャッシュする必要があり、次に同じサブディレクトリをfind
調べるときは速くなければなりません。何度もチェックするのは最適ではないように見えるかもしれませんが、これを最適化しようとするとコードが複雑になるため、それほど価値がありません。 grep -m 1
最初の一致後に終了しますが、このオプションは移植可能ではありません。grep
サポートしていない場合は使用-m
しないでください(つまり、使用してくださいgrep -q .
)。スクリプトは遅くなりますが、動作します。find-sh
説明は次のとおりです。の2番目のshは何ですかsh -c 'some shell code' sh
?- タイトルには「他のユーザーが何も所有していない場合」と呼ばれていますが、例とユースケースには「他のユーザーがサブディレクトリを所有していない場合」と記載されています。私のスクリプトは(サブ)ディレクトリのみをチェックします。 「そうでない場合...」を確認するには、
-type d
内部呼び出しのテストを無視してくださいfind
。 Permission denied
エラーは誤った肯定を引き起こす可能性があります。