開発プロジェクトには便利ツールみたいなものを作って生産性アップの夢を見ることが多いです。 いまのプロジェクトでもその例外に漏れず、WIndows と Mac の二者がいるということもあって、node.js で CLI ツールを作っています。
そこで抱えている課題は、いろんなところにいろんなツールが置かれた結果として package.json
が散在しているということ。
いろんなところで {yarn,npm} install
することになってとにかく面倒だったので、
package.json
があるディレクトリに移動yarn install
する
というのをサクっとやる方法が欲しかった。再帰的に package.json
を見つけるのは find
でできるんですが、上記のことを連続でやるのは厄介です。 なんでかっていうと、以下が理由。
find -exec
やxargs
で 2 つのコマンドを同一シェル上で実行することができない (と理解している)node_modules
配下には山のようにpackage.json
があって、それは除外したい
というわけで、それをどう実行すれば良いかを考えました。
方法 1
$ find . -type d -name node_modules -prune -o -type f -name package.json -print0 | xargs -0 -I{} sh -c 'cd $(dirname {}); yarn install'
まず find
で node_modules 配下にはない package.json
を探します。このパターンについては -name [それ以上下りたくないディレクトリ] -prune -o [実際に探したいファイルの条件]
というのがぼくのイディオムです。良く引用するんですが、このあたりは以下を参照いただければ。
package.json
があるディレクトリを見つけたら、その後は xargs
で実行します。
対象ディレクトリは dirname
で取れるので、そこに cd
したあとで yarn install
すれば良い。
xargs
で複数コマンドをどう実行したものかと思ったんですが、 sh
を起動してやれば良かった。シンプルだった。
方法 2
こっちは試してないんですが、たぶん動く。何を使うかというと、 find
には -execdir
というオプションがあります。
これは、「対象ファイルがあるディレクトリをカレントディレクトリとして、exec
を実行する」というもの。
-execdir utility [argument ...] ; The -execdir primary is identical to the -exec primary with the exception that utility will be executed from the directory that holds the current file. The filename sub- stituted for the string ``{}'' is not qualified.
これを使うと、上記はもっとシンプルに
$ find . -type d -name node_modules -prune -o -type f -name package.json -execdir yarn install \;
と書けるはず。