検索方法 -f -print -o -name と入力します。 -o -pruneは本当に動作しますか?

検索方法 -f -print -o -name と入力します。 -o -pruneは本当に動作しますか?

git背景として、私はhp-ux 11.11(11v1)システムを使用しています。多くのファイルを除外するために、広範囲の.gitignoreファイルを作成しています。私の.gitignoreはデフォルトで「このディレクトリを除くすべてを無視しますが、このディレクトリの下のこれらのパターンも無視します」と言います。正確な方法と理由は質問と完全には関係ありません。

git add私の目標は、実行する前に期待した結果が得られたことを確認することですgit add。これを達成するために、指定されたディレクトリ内のファイルに対してテストを実行していますgit check-ignore

私のアプローチは一般的に次のとおりです。

find test2 -type f -exec git check-ignore -v -n {} \; grep !

明確にするために、リポジトリはルートディレクトリ(/.git)(実際には/baz/dev/myRepo/.gitにシンボリックリンクされています)にあるため、git status/から呼び出します。また、パスが私が見ているものと一致し、アクションが返されたgitパスの形式と一致するようにfind from /を呼び出します。find-exec

標準出力は次のとおりです。

.gitignore:208:!test2/backupScripts/**  test2/backupScripts/CV_PostJob.sh
.gitignore:208:!test2/backupScripts/**  test2/backupScripts/CV_PostJob.sh.old
.gitignore:208:!test2/backupScripts/**  test2/backupScripts/CV_PreJob.sh
.gitignore:208:!test2/backupScripts/**  test2/backupScripts/CV_PreJob.sh.old
.gitignore:208:!test2/backupScripts/**  test2/backupScripts/CV_ScanCheck.sh
.gitignore:208:!test2/backupScripts/**  test2/backupScripts/oldCH.txt
.gitignore:212:!test2/scripts/**        test2/scripts/deprecated/CommvaultBackupScript.sh
.gitignore:212:!test2/scripts/**        test2/scripts/deprecated/NetBackupScript.sh
.gitignore:212:!test2/scripts/**        test2/scripts/benchmark.sh
.gitignore:212:!test2/scripts/**        test2/scripts/migrateVolumeSync.sh
.gitignore:212:!test2/scripts/**        test2/scripts/test.sh
.gitignore:206:!test2/* test2/CommvaultBackupScript.sh
.gitignore:206:!test2/* test2/NetBackupScript.sh
.gitignore:206:!test2/* test2/benchmark.sh
.gitignore:206:!test2/* test2/test.sh

通常、この手法はうまく機能しますが、場合によっては.gitignoreのパターンによって除外される多数のファイルを含むディレクトリが/test2/fooあります。/test2/bar

#Ignore everything
*

#add back /test2
!test2
!test2/**
#reignore foo and bar
test2/foo
test2/bar

find test2 -exec git check-ignoreしたがって、重要な質問は次のとおりです。列挙せずにコマンドを書かなくてもtest2 / fooとtest2 / barを実行できるようにしたいです。find test2 -name foo -prune -o -name bar -prune -o -type f -exec git check-ignore {} \;特に、無視されたサブディレクトリが12個である可能性がある場合は、実際にはtest2 /のファイルが正しく含まれていることを確認してから、再度実行してtest2 / backupScriptsなどの小さなサブディレクトリを確認してください。

find . -type f -print -o -name . -o -prune最終的にPOSIX準拠のコマンドを-execで実行して、findが相対パスではなく絶対パスであるgit check-ignoreにパスを渡すように調整したいと思います。しかし、このコマンドが正確にどのように機能するのかわかりません。実際に実行されているルートディレクトリのみを検索することを確認できます。

私の仕事は、最新バージョンのfindutilsがなく、プラットフォームで利用可能なGNU findutilsがないという事実によって制限されています。したがって、-maxlength オプションは使用できません。

export GIT_DISCOVERY_ACROSS_FILESYSTEM=1また、/ test2はマウントポイントであるため、/.gitのリポジトリに対してtest2でgitを実行するには、マウントポイントの境界をナビゲートできるようにGit環境()を変更する必要があります(cd test2 && find . -type f -exec git check-ignore --no-index -v -n {} \; -o -name . -o -prune | grep !現在はうまく機能します)。可能であれば(システムでGitを他の目的に使用するため)、これをしたくありません。

それでは、正確にどのように機能しますかfind . -type f -print -o -name . -o -prune? 1つ以上の点を/から呼び出すことができるいくつかのパス指定に置き換えることで変更できますか?それとも、オプションがこの特定の順序で提供されたときに特定の機能を実行する一種の「魔法」(たとえば、オプションがこの順序で提供されている場合にのみ目的の動作が導出される可能性があります)ですか?この特定のコマンドをGoogleで検索すると、この特定の回答自体を複数の言語で再公開する以外に何も返されないようです。再帰検索なし

私は次のようにしてこの特定のコマンドの動作を分析しようとしました。

cd /
find test2 -type f -print -o -name . -o prune
#no output

cd /test2
find . -type f -print -o -name . -o -prune
#get files in CWD as expected

find . -type f -print 
#gives me all files and directories below this, as you would expect

find . -type f -print -o -name . 
#gives the same as the prior command

find . -name . 
#gives just the CWD entry (.)

find . -name . -o -prune 
#gives just the files and folders in CWD, including the (.) entry

cd /
find test2 -name test2 -o -prune 
#also gives the files and folders directly in test2, including test2 itself

find test2 -name test2 -o -prune -o -type f -print 
#no output

find test2 -name test2 -prune 
#returns just test2 itself

find test2 -type f -print -o -name test2 -prune 
#predictably gives no output, as test2 is pruned

find test2 -type f -print -o -name foo -prune 
#gives full directory list except for /test2/foo, as expected.

find test2 -type f -print -o -name "test2/*" -prune 
#gives full directory list, as a / will never be in the "base" name which find tests.

cd /
find test2/* -type f -print -o -prune 
#this is the closest, same as "find . -name . -o -prune" but with cd to test2 first.

答え1

find . -type f -print -o -name . -o -prune

より正式なアプローチと比較して、サブディレクトリの代わりに現在のディレクトリで一般的なファイルを見つけるより洗練された方法は次のとおりです。

find . ! -name . -prune -type f

GNU実装を使用して作成することもできますfind(またはGNUfind-mindepth/implementationコピー-maxdepth)。

find . -mindepth 1 -maxdepth 1 -type f

-mindepthこの場合、重複するため(深さ0)は-type f除外されます.。)

存在する:

find . -type f -print -o -name . -o -prune

.findファイル検索が開始されるファイルです。

.は通常のファイル自体ではないため、印刷されず、最初のファイル-oの右側の部分がテストされます。-name .一致するため、式は true として検証され、-prune実行されません。なぜなら、全式findには a-printが含まれているからです。行動述語、そのファイルの完全な式が true と確認されても、暗黙的に何も印刷されません。

これで.クリーンアップ操作がなくディレクトリなので、findその内容を読み取り、その中のすべてのファイル(特殊項目を除く)に式が適用され.ます..

これを行うには、次の種類のファイルについて定期的な-print実行されます。他の種類のファイルでは、-name .一致するものがないので-prune実行されます。そのディレクトリ・タイプ・ファイルの場合、これはfindそのファイルに降りることができないことを意味します。

したがって、重要な点は次のとおりです。

  • 定期的なfタイプ)印刷するファイル
  • .(最上位ディレクトリ)以外のディレクトリはクリーンアップされているため、findは子ディレクトリにドロップダウンされません。

答え2

からman find

-prune
True; if the file is a directory, do not descend into it.

通常、-pathオプションと一緒に使用されます。

find $HOME -path $HOME/.config -prune \
  -type f -mtime 0

今日変更されたファイルは検索され無視さ$HOMEれます。$HOME/.config

関連情報