findコマンドの-depthオプションのGNU版とBSD版の違いでハマったという話

なにごと?

find コマンドで「1階層目のファイル/ディレクトリだけを列挙したい」となり*1macOS$ man find したら -depth オプションを使えばよさそうだったので、こんなふうにしてたわけです。

$ find . -depth 1

で、これをGitHub ActionsでやっているCI(ubuntu-latestなイメージ)に組み込んだら、こんなエラーが。

find: paths must precede expression: `1'

よく見てみると、findコマンドのオプションがBSD版とGNU版で異なるためにエラーになっている様子。 というわけで、ちゃんとマニュアルを読んでみる。

環境

BSD版の -depth

-depth n

True if the depth of the file relative to the starting point of the traversal is n.

https://www.freebsd.org/cgi/man.cgi?find(1)

つまり、指定したパスの開始点から深さ n のファイルやディレクトリが列挙される。

ちなみに引数 n を取らない -depth オプションもある。

-depth

Always true; same as the non-portable -d option. Cause find to perform a depth-first traversal, i.e., directories are visited in post-order and all entries in a directory will be acted on before the directory itself. By default, find visits directories in pre-order, i.e., before their contents. Note, the default is not a breadth-first traversal.

https://www.freebsd.org/cgi/man.cgi?find(1)

こっちは深さ優先探索にするオプションらしい。

GNU版の -depth

-depth

ディレクトリそのものより先に、ディレクトリの中身を処理する。 アクション -delete を使用すると、-depth オプションも自動的に設定される。

https://linuxjm.osdn.jp/html/GNU_findutils/man1/find.1.html

つまり、BSD版の -depth (引数を取らないほう)と同じく深さ優先探索になる。 引数を取る -depth n は無い。このため、前述のエラーになっていたということらしい。

GNU版でもBSD版の -depth n みたいに特定の階層のみ列挙したい場合は?

-mindepth-maxdepth を組み合わせればよい。 下記のようにすれば、1階層目のファイル/ディレクトリだけが列挙される。

$ find . -mindepth 1 -maxdepth 1

*1:これだけだと「lsでいいじゃん」ってなるのですが、実際にはもうちょっと細かい条件があって、findが適切だったのです