findコマンドを使用してディレクトリツリーを再帰的に検索し、指定された名前と一致するディレクトリのすべての結果を返します。
find . -type d -name '<NAME>'
ログファイルに印刷される返されたパスのリストを取得します。親ディレクトリにomit.txtというファイルを含む結果を無視できるようにしたいです。
./parent_directory/名前>
私はこれを持って努力してきました。
find . -type d -name '<NAME>' \( ! -wholename "*omit.txt*" -prune \)
ファイルを含む結果を無視するためにpruneコマンドを使用しようとしていますが、この方法はディレクトリにのみ適用されるようです。どんな助けでも大変感謝します。 1つのコマンドでこれを行い、出力ファイルをできるだけ維持したいと思います。
答え1
find
作業中にディレクトリ内のファイルを表示できる必要があるため、内部でこれを正しく実行することはできないと思います。-prune
ディレクトリ自体は機能する必要がありますが、他の条件ではディレクトリ自体に置かれたファイル名のみが表示されます-path
。find
私が考えることができるのは、シェルを分離してディレクトリの内部を見るだけです。このような:
$ mkdir -p x y/z ; touch x/foo y/omit.txt
$ find -type d \( -exec sh -c '[ -e "$1/omit.txt" ]' sh {} \; -prune -o -print \)
.
./x
foo -o bar
bar
成功は評価されないため、foo
ディレクトリがクリーンアップされると印刷は実行されません。-o -print
最後に追加すると、ディレクトリの内容も印刷できます。exec ... {} +
各ディレクトリの条件として個別に必要なため、ここでは使用できません。
答え2
システムでbusyboxが利用可能な場合は、次のことができます。
busybox find . -type d '(' -exec [ -e '{}/omit.txt' ] ';' -prune \
-o -name '<NAME>' -print ')'
busyboxはfind
GNUと同様に{}
ファイルパスまで拡張されます。部分この主張はこれに頼る必要を避けますsh
が、もっと重要なのは、最新バージョンではfork()またはexecve()なしで小さなプログラムを実行できるため、他のほとんどの実装Magnitudeよりも数倍効率的です[
。find
名前付きディレクトリ<NAME>
自体にaが含まれている可能性があり、omit.txt
その場合はそれを印刷したい場合は、まだ切り捨てられても次のように変更できます。
busybox find . -type d '(' -exec [ ! -e '{}/omit.txt' ] ';' -o -prune ')' \
-name '<NAME>'
bash以外のboshシェルにはfind
(like [
)が組み込まれており、-call
その述語を分岐することなくいくつかのシェルコードを実行できます。これはfork()とexecve()も節約します。
find . -type d '(' -call '[ -e "$1/omit.txt" ]' {} ';' -prune \
-o -name '<NAME>' -print ')'
より移植性に優れた代替手段find
は のFile::Find
モジュールを使用することです。
perl -MFile::Find -le '
find sub {
if (-e "$_/omit.txt") {
$File::Find::prune = 1;
} else {
print $File::Find::name if ($_ eq "<NAME>") && -d;
}
}, @ARGV' -- .
答え3
@ilkkachuがしばらく私を悩ませてきた質問に素晴らしい答えを与えました!彼らにぜひ投票してください。私は他の人に役立ついくつかのバリエーションを追加したかったです。 :)
出力例は、次の構造に基づいています。
./
├── a/
│ ├── b/
│ │ └── world.txt
│ └── hello.txt
├── foo.txt
└── some_git_repo/
├── .git/
├── README
└── c/
└── some_git_submodule/
├── .git/
└── README
git reposを除くすべてのディレクトリを印刷します。
find . -type d \( -exec sh -c 'test -e "$1/.git"' sh {} \; -prune -o -print \)
.
./a
./a/b
1. git reposを含むすべてのディレクトリを印刷します。
2. Gitリポジトリに再帰しないでください。
find . -type d \( -exec sh -c 'test -e "$1/.git"' sh {} \; -print -prune -o -print \)
.
./a
./a/b
./some_git_repo
gitリポジトリのファイルを除くすべてのファイルを印刷します。
find . \( -exec sh -c 'test -e "$1/.git"' sh {} \; -prune -o -type f -print \)
./foo.txt
./a/b/world.txt
./a/hello.txt
1. git reposのファイルを除くすべてのファイルを印刷します。
2.除外されたgitディレクトリの印刷
find . \( -exec sh -c 'test -e "$1/.git"' sh {} \; -print -prune -o -type f -print \)
./foo.txt
./a/b/world.txt
./a/hello.txt
./some_git_repo
それから反対...
すべてのGitリポジトリを印刷
find . -type d \( -exec sh -c 'test -e "$1/.git"' sh {} \; -print -prune \)
./some_git_repo
サブモジュールを含むすべてのgitリポジトリを印刷します。
find . -type d \( -exec sh -c 'test -e "$1/.git"' sh {} \; -print \) -o \( -name '.git' -prune \)
./some_git_repo
./some_git_repo/c/some_git_submodule