私のOSXでは、次のようにfind
デフォルトのBSDと一緒にGNUをインストールしました。find
brew install findutils
私が知る限り、BSDはfind
POSIX標準に準拠し、GNUはそれをオプションにします(これによると郵便はがき)、これは予想される出力に多くの不一致を引き起こします。
たとえば、
BSDルックアップ
$ find -L /etc -execdir echo {} ';' | head
etc
AFP.conf
afpovertcp.cfg
aliases
aliases.db
apache2
extra
httpd-autoindex.conf
httpd-dav.conf
httpd-default.conf
GNUを探す
$ gfind --version
find (GNU findutils) 4.4.2
$ POSIXLY_CORRECT=1 gfind -L /etc -execdir echo {} ';' | head
/etc
/etc/AFP.conf
/etc/afpovertcp.cfg
/etc/aliases
/etc/aliases.db
/etc/apache2
/etc/apache2/extra
/etc/apache2/extra/httpd-autoindex.conf
/etc/apache2/extra/httpd-dav.conf
/etc/apache2/extra/httpd-default.conf
gfind: `echo' terminated by signal 13
gfind: `echo' terminated by signal 13
... endless loop here
-L
注:上記のリンクを私の/etc
リンクとして使用していますprivate/etc
。
GNU find マニュアルで POSIX 標準に従うことを指定できることがわかりますが、POSIXLY_CORRECT
上記の例ではこれは機能しません。
上記の例では、GNU findが同じ出力を持つように強制する別の方法があります(例:POSIX標準)。
無限ループに加えて、GNUは相対ファイル名を印刷しますが、BSDがフルパスを印刷するのはなぜですか?
ベストアンサー1
これはない無限ループこれは、SIGPIPEを使用してGNUが死亡をfind
報告することですecho
(なぜなら、stdoutのパイプのもう一方の端はhead
死亡時に閉じていたからです)。
-execdir
POSIX が指定されていません。ために-exec
何もないPOSIX仕様これは、コマンドが SIGPIPE によって終了した場合にfind
終了する必要があることを意味します。
-execdir
したがって、POSIXが指定されている場合、gfind
BSDよりもPOSIX仕様が高くなる可能性がありますfind
(質問が示すように、サブプロセスがSIGPIPEで終了したときにBSDが終了を見つけたと仮定すると、FreeBSDはfind
私のテストに含まれておらず実行されます)。echo
ループ内各ファイルについて(GNU findのように無限ではありません)。
最も一般的なケースでは、find
SIGPIPEのために子が終了すると終了する方が良いと主張することができますが、-exec
tedコマンドは標準出力でパイプを閉じること以外の理由でSIGPIPEによって終了する可能性があるため、終了することはfind
許可されます。
GNUを使用すると、コマンドが失敗した場合に終了するfind
ように指示できます。find
find . ... \( -exec echo {} \; -o -quit \)
find
実装がstderrでchild-deathシグナルを報告することを許可するのか、それとも許可しないのかについては、ここを使ってとにかく-execdir
POSIXの範囲外ですが、代わりに使用すると-exec
gfind-execdir
非準拠のケースになりそうです。
仕様は次のようにfind
言います。「標準エラーは診断メッセージに固有です。」だけでなくそこで言った:
デフォルトの動作:このセクションが「標準エラーは診断メッセージにのみ使用する必要があります」とリストされている場合、特に明記しない限り、終了ステータスがエラーが発生したことを示す場合にのみ、診断メッセージを標準エラーに送信する必要があります。ユーティリティは、このボリュームのPOSIX.1-2008で説明されているように使用されます。
これはfind
、この場合、ゼロ以外の終了ステータスは返されないため、stderrにメッセージを出力しないことを示します。
このテキストによると、find
GNUとFreeBSDはどちらも次の状況で非準拠です。
$ find /dev/null -exec blah \;; echo "$?"
find: `blah': No such file or directory
0
どちらもエラーを報告しますが、終了ステータスをゼロ以外に設定しません。だから私はこの質問は、オースティングループ(POSIXの背後にある人)メーリングリストで質問されました。。
コマンドを次のように変更した場合は注意してください。
(trap '' PIPE; find -L /etc -execdir echo {} \; | head)
echo
それでもすべてのファイルで実行され、まだ失敗しますが、今回はecho
エラーメッセージが報告されます。
これでfilename
vs /etc/filename
vsの内容./filename
が示されています。
-execdir
繰り返しますが、基準オプション、誰が正しいかどうかを示すテキストはありません。-execdir
これはBSDによって導入され、find
後でGNUによってコピーされましたfind
。
GNUはfind
意図的にいくつかの変更(改善)をしました。たとえば、./
コマンドに渡された引数にファイル名を追加します。これはfind . -execdir cmd {} \;
、exampleで始まるファイル名に問題がないことを意味します。-
実際に-L -execdir
親ディレクトリに基づいてファイルパスを渡さないのは、実際には抜け穴GNUバージョン4.3.0〜4.5.8に影響しますfind
。 4.5.9で修正されましたが、開発ブランチにあり、まだ新しいブランチはありません。安定出版以降(2015年12月22日現在、差し迫った)。
詳細については、findutilsメーリングリストを参照してください。。
必要なのがPortable各ファイルのデフォルト名を印刷することであれば、/etc
次のようにすることができます。
find -L /etc -exec basename {} \;
またはより効率的に:
find -L ///etc | awk -F / '/\/\// && NR>1 {print last}
{if (NF > 1) last = $NF
else last = last "\n" $NF}
END {if (NR) print last}'
次のように単純化できます。
find -L /etc | awk -F / '{print $NF}'
ファイルパスに改行文字が含まれていないことを確認できる場合(IIRC、一部のOS / Xバージョンは/ etcに対応するファイルがあります)
GNUly:
find -L /etc -printf '%f\n'
かどうかについて:
find -exec echo {} \;
内部に協会POSIXに言及していますか?
いいえ、コマンド呼び出しとして、これはPOSIXではありません。 ㅏスクリプトこれは非準拠です。
POSIXでは、find
少なくとも1つのパスを指定する必要がありますが、オプションではない最初の引数がorで始まり、述部find
(-
たとえばfind
、!
または(
)の場合、指定されていない動作は維持されるため、GNUfind
動作は維持されます。はい互換性、バグ報告(または照会述語を表しても最初の引数をファイルパスとして扱う)、実装の顔に赤いペイントを散布するなど、それが動作にPOSIXLY_CORRECT
影響を与える理由はありません。find