2015年11月20日金曜日

learnyounodeを解いてみる(5問目)

learnyounode [ FILTERED LS]

拡張子によってフィルタしたファイルリストをコンソールに出力するアプリを書いてください。


5問目は、指定した拡張子のファイルを列挙するアプリです。シェルコマンドで言えば「find -name ".拡張子"」の様な結果になるということですね。
 1つめの引数にフォルダのパスを入れ、2つめの引数に拡張子を指定します。2つめの拡張子は拡張子名のみ、("."抜き)で指定とあります。

とりあえず、ファイルの列挙から始めましょう。
非同期でとありますので、ファイル列挙は fs.readdir を使用します。第一引数にパス、第二引数にはコールバック関数です。 Nodeのコールバック関数はcalback(err, list)のパターンが定番なので覚えておきましょう。listは得られたファイルの配列です。

fs.readdir


readdir.js
var fs = require("fs");
var dir = ".";

fs.readdir(dir, function(err, list) {
    if(err) throw err;
    for(var i in list) {
 console.log(list[i]);
    }
});

上の例ではパスがカレントディレクトリで固定されているので引数を指定せず、そのままカレントディレクトリ内のファイルが列挙されるはずです。
if (err) throw err; もエラーをthrowさせるNodeのイディオムなので無くても正常であれば動作します。
forは得られた配列を展開しているだけなので、イテレータ「files.forEach(function (file) { }」でもいけます。

得られたファイルリストから拡張子を抜き出すには、文字列操作を使っても構いませんがヒントに拡張子を抜き出すNodeのpathモジュールを使うと役に立つと書いてあるのでpathモジュールのextname関数を使用します。extname関数は引数にファイルを入れると拡張子だけ抜き出してくれます。それを判定に使えばいけますね。

path.extname


気をつけることは引数には拡張子名だけ指定してextnameで抜き出せる拡張子が"."付きだということです。なので"."を足してから比較します。
あとは引数と得るのは先回使ったprocess.argv[N]なので組み合わせて完了です。

extname.js
var fs = require("fs");
var path = require("path");

var dir = process.argv[2];
var ext = process.argv[3];

fs.readdir(dir, function(err, list) {
    if(err) throw err;
    for(var i in list) {
   if(path.extname(list[i]) == '.' + ext) {
      console.log(list[i]);
   }
    }
});

$ learnyounode verify extname.js 

...................

# おめでとう!

「LSのフィルター」に対するあなたの回答は合格です!

これが正式な回答です(もしあなたの回答と比較してみたいならどうぞ):

─────────────────────────────────────────
    var fs = require('fs')
    var path = require('path')
    
    fs.readdir(process.argv[2], function (err, list) {
      list.forEach(function (file) {
        if (path.extname(file) === '.' + process.argv[3])
          console.log(file)
      })
    })

0 件のコメント:

コメントを投稿