
辞書:これは一般的な問題(すべてのフォルダに当てはまると仮定)から特定の極端なケースに発展しました。
私のように気になる方もいらっしゃるようで質問を削除せずに書き直すことにしました。
自分のホームフォルダに直接含まれているすべてのアイテム(ドットファイルとフォルダを除く)を一覧表示したいとします。 IMHO 次の find コマンドがこれを行う必要があります。.hidden
(ファイルを使用すると「隠しプロジェクト」が異なる場合があるため、「ドットプロジェクト」と明示的に書きました):
find $HOME/ -mindepth 1 -maxdepth 1 -path "$HOME/.*" -prune -o -print
-mindepth 1
$HOME自体を含めず、1つの-maxdepth 1
フォルダレベルに制限し、-path "$HOME/.*" -prune
ホームフォルダからドットで始まる項目を除いて、-o -print
デフォルトマニュアルページ。
今まではそんなに良くなった。それは一種の働きます(無許可のドットフォルダがあるが)。しかし、$HOME/.gvfs
まったくアクセスできないはずですが、次の理由で窒息し始めます-path ... -prune
。
/home/user/file a
/home/user/folder b
...
find: '/home/user/.gvfs': Permission denied
/home/user/.gvfs
...
/home/user/file z
-perm
atを使っfind
て2> /dev/null
解決できるということはわかるが、私が本当に驚いたことは、/home/user/.gvfs
すでにリストに含まれています。(他のすべてのポイントアイテムは除外されますが)! ! !
私は、観察力が不足している一部の人々がエラーを振り返り、進み続けようと努力2> /dev/null
すると確信しています。 ...もし1> /dev/null
100行の長いリストは、コマンドを使用する前にaddなどのメソッドを使用して明示的にエラーを確認する必要があるため、完全にエラーを認識します。
ディレクトリ/ツリーは実際に無視されますか?
なぜこれが防止されるのか、少なくとも防止されるべきであるにもかかわらず、アクセスを試みるのはなぜですかfind
?たとえば、マニュアルページから:/home/user/.gvfs
-maxdepth 1
-prune
'-prune'操作(のみさらなる落下防止[...])
私のシステムにインストールされている以前のマニュアルページにも-path
次のように記載されています。
到着完全なディレクトリツリーを無視、ツリー内のすべてのファイルを確認するのではなく、-pruneを使用してください。
「無視された」ディレクトリ自体の危険なリストです!
すべてが実際に無視される場合、/home/user/.*
私の質問の2番目の部分は必要ないかもしれません。これは内部エラーによるものです。
なぜ/home/user/.gvfs
まだリストにあり、どのように防ぐことができますか?-user
/-perm
および2> /dev/null
すべてのfind
コマンド(少なくとも作業-prune
)を操作する必要がない方法はありますか?
今後の活用 - >効率性?
実際に無視されている-prune
(または少なくとも無視される-path ... -prune
)ものは何ですか?
(ほとんど)すべてのファイルがまだスキャンされている場合は、この複雑なオプションの使用を放棄し、代わりにorを-prune
使用します。特にエラーが発生しやすいので、さらにそうです。
!
-not
-prune
答え1
そうだ間違いGNU実装では、find
トリガーは(ファイルのメタデータを取得する)システムコールであるlstat()
ようです。fstatat()
EACCESS
許可が拒否されました)ファイルに.gvfs
。
これは通常、ファイルがFUSEベースのファイルシステムのマウントポイントであるため、Linuxで発生しますが、-o allow-other
このオプションは使用されていません。これは、アクセスできない領域を指すシンボリックリンクがある場合でも発生する可能性がfind -L
あります。find -follow
ここで私が見つけたのは、-prune
これらのファイルに対して返されることです。間違った-prune
文書化された(およびPOSIX必須)常に返されるように、これは明らかにバグです。本物。
バグが修正されるまで、回避策として次のよう-prune
に置き換えることができます'(' -prune -o -true ')'
。 (これは-true
GNU拡張です。移植可能な拡張も可能です! -name ''
が、移植可能な拡張は正しいことを保証します。'(' -prune -o ! -prune ')'
)
今、コード自体にいくつかの問題があります。存在する:
find $HOME/ -mindepth 1 -maxdepth 1 -path "$HOME/.*" -prune -o -print
- ほとんどのBourne様シェルでは
$HOME/
これを引用する必要があります。それ以外の場合、$HOME
拡張は分割+グローブの影響を受けます。これを書くこともできます~/
。 -prune
find
ディレクトリに入らないように言いました。最上位(深さ0)ディレクトリを除くすべてのディレクトリに降りるmaxdepth 1
のをやめるので、ここでは重複します。find
$HOME/
-path
パターンを採用してください。これは、コンテンツが$HOME
パターンとして処理されることを意味します。$HOME
たとえば、あなたが裏面/home/[112] me
では一致しますが、-path '/home/[112] me/.*'
一致しません。また、ここではフルパスを一致させる必要はなく、代わりにファイル名を一致させることもできます。/home/2 me/.foo
/home/[112] me/.foo
-name '.*'
*
GNUのみfind
一致数値したがって、次.*
から始まるファイル名と一致します。.
そしてまた、有効な文字を形成する一連のバイトで構成されます。したがって、C
各バイトシーケンスが有効な文字(ロケールなど)を形成するロケールの隠しファイルを一致させるためにのみ使用できます。
したがって、ここで要点がフルパスでHOMEディレクトリに隠されていないファイルを一覧表示することである場合は、次のことができます。
LC_ALL=C find ~/ -mindepth 1 -maxdepth 1 ! -name '.*'
これはまた、GNUfind
エラーを防止します。
または標準の等価項目(/./
パスにaを追加しても):
LC_ALL=C find ~/. ! -name . -prune ! -name '.*'
find
(ここではファイルでGNUエラーが発生します。いいえ始めることは.
不可能ですlstat()
が、上記のエラーの説明に示すように、lstat()
不可能なファイルが報告されるかどうかは実装ごとに大きく異なります。
ここでは以下を使用しますzsh
。
print -rC1 ~/*(ND)
または、次のようにソートしたくない場合find
:
print -rC1 ~/*(NDoN)