findコマンドの-depthオプションのGNU版とBSD版の違いでハマったという話
なにごと?
find
コマンドで「1階層目のファイル/ディレクトリだけを列挙したい」となり*1、macOSで $ 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
.
つまり、指定したパスの開始点から深さ 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.
こっちは深さ優先探索にするオプションらしい。
GNU版の -depth
-depth
ディレクトリそのものより先に、ディレクトリの中身を処理する。 アクション -delete を使用すると、-depth オプションも自動的に設定される。
つまり、BSD版の -depth
(引数を取らないほう)と同じく深さ優先探索になる。
引数を取る -depth n
は無い。このため、前述のエラーになっていたということらしい。
GNU版でもBSD版の -depth n
みたいに特定の階層のみ列挙したい場合は?
-mindepth
と -maxdepth
を組み合わせればよい。
下記のようにすれば、1階層目のファイル/ディレクトリだけが列挙される。
$ find . -mindepth 1 -maxdepth 1
*1:これだけだと「lsでいいじゃん」ってなるのですが、実際にはもうちょっと細かい条件があって、findが適切だったのです