TECH BOX

Technology blog from Web Engineer

この記事は最終更新日から6年以上経過しているため正確ではないかもしれません

Node.jsを使ってファイルを再帰的に取得

webpackを使っているとディレクトリ構造のまま出力したいとか思ったりします。
そんな時はNode.jsの機能を使って、指定したディレクトリ配下の特定の拡張子のみを取得することができます。

ソース

// getFileList
import path from 'path'
import glob from 'glob'

export default function(dir, ext){
  let ws = path.resolve(dir)
  let file_list = glob.sync(`${ws}/**/[!_]*.${ext}`)

  let reg1 = new RegExp(`${ws}/`)
  let reg2 = new RegExp(`.${ext}$`)

  let entries = {}

  file_list.forEach(item=>{
    let key = item.replace(reg1, '')   // ワークスペース名の削除
    key = key.replace(reg2, '')   // 拡張子の削除
    entries[key] = item
  })

  return entries
}

使い方

import getFileList from './getFileList'
let pug = getFileList('_ws/pug', 'pug')

上記の場合_ws/pug内のpugファイル一覧を取得します。

説明

パスの解決とファイルリストの取得

let ws = path.resolve(dir)
let file_list = glob.sync(`${ws}/**/[!_]*.${ext}`)

まずはpathのresolve関数を使ってフルパスに変更します。

glob.syncの部分はgulpを使っている人なら見覚えがあると思いますが、これはglobパターンと言って、正規表現とは違う独自のパターンで指定することができます。

上記の場合はワークスペース内のアンダースコアが先頭についていないかつ指定した拡張子のファイルリストを下階層まで取得します。

ファイルリストのファイル名をKEYにしつつ、ファイルパスを格納

let reg1 = new RegExp(`${ws}/`)
let reg2 = new RegExp(`.${ext}$`)

let entries = {}

file_list.forEach(item=>{
  let key = item.replace(reg1, '')   // ワークスペース名の削除
  key = key.replace(reg2, '')   // 拡張子の削除
  entries[key] = item
})

変数を正規表現に入れ込む場合はRegExpを使うと便利です。
ここではkey名のためにワークスペース名と拡張子をreplaceしています。

結果

仮に下記のようなファイル構成があるとします。

/_ws/
  └ /pug/
      ├ index.pug
      ├ _test.pug
      └ /foo/
          ├ index.pug
          ├ bar.pug
          └ _test.pug

これをlet pug = getFileList('_ws/pug', 'pug')で実行すると下記の結果が返却されます。

{
  index: 'path/to/_ws/pug/index.pug',
  'foo/index': 'path/to/_ws/pug/foo/index.pug',
  'foo/bar': 'path/to/_ws/pug/foo/bar.pug',
}

webpackの場合、outputにこれを代入すればディレクトリ構造を保ったまま出力することができます。


※Javascript Standard Styleのルールで記述しています