ham-capのブログ

プログラミング学習の記録

【Ruby】カレントディレクトリのファイル名を取得する(隠しファイル込み)

したいこと

カレントディレクトリに存在するファイル・ディレクトリの名前を取得したい。隠しファイルの名前も取得したい。

※以下、この記事中ではファイルという呼び方ばかり使っていますが、基本的にディレクトリも含んでいると考えてください

Dirクラス

結論から言うと、Dirクラスのglobメソッドをつかえばいけます。

どう書けばいいかを端的に知りたい方は一番下までスクロールしてもらえればすぐコードが見られます。

docs.ruby-lang.orgdocs.ruby-lang.org

ワイルドカードの展開を行い、パターンにマッチするファイル名を文字列の配列として返します。パターンにマッチするファイルがない場合は空の配列を返します。 ブロックが与えられたときはワイルドカードにマッチしたファイルを引数にそのブロックを 1 つずつ評価して nil を返します

とのこと。 書式としてはglob(pattern, flags = 0, base: nil, sort: true)のようになりますが、第1引数のpattern以外は省略できます。 指定したワイルドカードのパターンと一致するファイル名を配列にして返してくれるメソッドです。 第1引数に指定できるワイルドカードは以下のとおり。

記号 意味
* 空文字列を含む任意の文字列
? 任意の一文字
[] 鈎括弧内のいずれかの文字
{} コンマで区切られた文字列の組合せに展開
**/ ワイルドカード */ の0回以上の繰り返し

正直**/とかはよく分からないけど今回は割愛。

で、今回のタイトルにあるとおりカレントディレクトリに存在する全てのファイルとディレクトリの名前を取得したい場合は、とにかく全ての文字列にマッチしてくれればいいので*を使ってDir.glob("*")とすればおk。秒殺。

ただし、ワイルドカードはデフォルトの挙動としてファイル名の先頭にある.にマッチしないようになっています。 つまり隠しファイルにはマッチしません。 でも隠しファイルの名前も含めて取得する必要がある場合もあると思います。 そんなときに使えるのが第2引数。 この部分にフラグを指定してやればマッチの挙動を変更できます。

フラグってなんやねんと思われる向きもあると思います。僕も思いました。 なので簡単に書いておきます。

File.fnmatch

リファレンスマニュアルでは、globメソッドの第2引数で使用できるフラグというのはFileクラスのfnmatchメソッドで使用されるものと同じだと説明されています。 ではFileクラスのfnmatchメソッドとは何でしょう。 これもリンクを貼っておきます。

docs.ruby-lang.org

ファイル名のパターンマッチ fnmatch(3) を行います。 path が pattern にマッチすれば真を返します。そうでない場合には false を返します。

というわけで、今回使っているDir.globと似たようなメソッドで、ワイルドカードにマッチするファイル名を返してくれます。 Dir.globとの細かい違いについては上記のリンクを参照してください。

肝心のフラグについてですが、以下の種類があります。

フラグ 使用時の挙動
FNM_NOESCAPE エスケープ文字 \ を普通の文字とみなす
FNM_PATHNAME ワイルドカード *, ?, []/ にマッチしなくなる
FNM_CASEFOLD アルファベットの大小文字を区別せずにパターンマッチを行う
FNM_DOTMATCH ワイルドカード *, ?, [] が先頭の . にマッチするようになる
FNM_EXTGLOB {} 内のコンマで区切られた文字列の組合せにマッチするようになる

そのままドンピシャで書いていますが、今回のように隠しファイルにもマッチしてほしい場合にはFNM_DOTMATCHを第2引数で使用すればいいということになります。 これらは定数で、File::FNM_NOESCAPEのような形で使用できます。

というわけで、隠しファイルも含めたカレントディレクトリのファイル名を取得するには、

Dir.glob("*", File::FNM_DOTMATCH)

とすればおkです。

息子さんが隠しているあんなファイルやこんなファイルも全て衆目に晒すことができます。いともたやすく行われるえげつない行為(D4C)ですね。

では、今回はこんな感じです。 最後まで読んでいただきありがとうございました。