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