【PHP】ディレクトリ内のファイル一覧取得&ソートする方法

公開日:
更新日:
カテゴリー: PHP

次の3つをまとめています。

①任意のディレクトリにあるファイルの一覧を取得する方法

②次のルールに従ってソートする方法

  • 名前(デフォルト)
  • 更新日時
  • サイズ
  • 種類

③glob関数について

ファイルの一覧取得

任意のディレクトリにあるファイルの一覧はglob関数で取得できます。

まず説明のために環境を整理します。

とあるディレクトリに下のようにファイルを入れています。

  • htmlファイル4つ
  • jpgファイル3つ
  • pngファイル3つ
  • phpファイル1つ

「index.php」に次のようなプログラムを書きます。

<?php
//glob関数でファイルの一覧を取得(配列)
$array = glob("*");

//出力
print_r($array);
?>

そしてこれを実行すると次のようになります。

Array
(
    [0] => 001.html
    [1] => 002.png
    [2] => 003.jpg
    [3] => 101.html
    [4] => 102.jpg
    [5] => 103.png
    [6] => aaa.html
    [7] => bbb.html
    [8] => ccc.png
    [9] => ddd.jpg
    [10] => index.php
)

操作したい場合

上の場合は単純にファイル名を出力しただけにすぎませんが、実際は一つ一つのファイルに操作をすることが多いと思います。

その場合はforeach関数を使って次のようにします。

<?php
//glob関数でファイルの一覧を取得(配列)
$array = glob("*");

//配列をループで処理
foreach($array as $file){
	//出力
	echo $file;
}
?>

これを実行すると次のようになりますが、foreach関数の中身をごにょごにょすればしたいことが何でもできます。

001.html
002.png
003.jpg
101.html
102.jpg
103.png
aaa.html
bbb.html
ccc.png
ddd.jpg
index.php

ソートする方法

上をみてわかるように、デフォルトでは名前順にソートされています。これをいろいろな条件でソートしてみます。

更新日時でソート

更新日時でソートするためには次のようにします。

  1. ファイルの更新日時を比較する関数を作る
  2. ファイルの一覧を取得する
  3. usort関数で配列をソートする

※ファイルの更新日時はfilemtime関数で取得できる
usort関数は、ユーザーが作成した比較関数を使用して配列をソートできる関数

上の流れをプログラムにまとめるとこうなります。

<?php
//ファイルの更新日時を比較する関数
$sort_by_last_modify = function($a, $b){
	return filemtime($b) - filemtime($a);
};

//glob関数でファイルの一覧を取得(配列)
$array = glob("*");

//usort関数で配列をルールに沿ってソートする
usort($array, $sort_by_last_modify);

//出力
print_r($array);
?>

これを実行すると、更新日時順(新しい順)にソートされます。

Array
(
    [0] => index.php
    [1] => 103.png
    [2] => ddd.jpg
    [3] => 002.png
    [4] => ccc.png
    [5] => 003.jpg
    [6] => 102.jpg
    [7] => 001.html
    [8] => 101.html
    [9] => aaa.html
    [10] => bbb.html
)

なお、更新日時を古い順にソートしたい場合は単純にarray_reverse関数を使って配列を逆に並べ替えればよいです。

<?php
//ファイルの更新日時を比較する関数
$sort_by_last_modify = function($a, $b){
	return filemtime($b) - filemtime($a);
};

//glob関数でファイルの一覧を取得(配列)
$array = glob("*");

//usort関数で配列をルールに沿ってソートする
usort($array, $sort_by_last_modify);

//配列を逆に並べ替える
$array = array_reverse($array);

//出力
print_r($array);
?>

ファイルサイズでソート

上と同じ方法でfilesize関数( ファイルサイズの取得関数 )を使えばファイルサイズでのソートも可能です。

<?php
//ファイルの更新日時を比較する関数
$sort_by_last_modify = function($a, $b){
	return filesize($b) - filesize($a);
};

//glob関数でファイルの一覧を取得(配列)
$array = glob("*");

//usort関数で配列をルールに沿ってソートする
usort($array, $sort_by_last_modify);

//出力
print_r($array);
?>

これを実行するとファイルサイズ順(大きい順)に並びます。

Array
(
    [0] => bbb.html
    [1] => aaa.html
    [2] => 101.html
    [3] => ccc.png
    [4] => 002.png
    [5] => 103.png
    [6] => 001.html
    [7] => 003.jpg
    [8] => 102.jpg
    [9] => ddd.jpg
    [10] => index.php
)

※配列をarray_reverseするとサイズが小さい順になる

ファイルの種類でソート

ソートというか、抽出といった方が正しいですが、glob関数は上で「*」を使っているように正規表現が使用可能です。

したがって、次のようにすればファイルの種類を指定してファイルをソート(抽出)することが可能です。

<?php
//glob関数でファイルの一覧を取得(配列)
$array = glob("*.html");

//出力
print_r($array);
?>

これを実行すると「HTML」ファイルのみ取得できることがわかります。

Array
(
    [0] => 001.html
    [1] => 101.html
    [2] => aaa.html
    [3] => bbb.html
)

glob関数について

glob関数はワイルドカードを使って任意のファイルやディレクトリを取得できます。ここからは自分の勉強を落とし込むためにglob関数についてまとめます。

基礎基本

glob関数はパターンにマッチする全ての「パス名」を配列で取得できる関数です。

glob(patern, option);

第1引数にはマッチパターンを指定し、第2引数にはオプションを追加します。

パターンにマッチした場合、戻り値は配列で返されます(パターンにマッチしなかった場合は空の配列が返される)。エラーが生じた場合は「false」が返されます。

glob関数の最大の特徴は、ワイルドカードを使って任意のファイルやディレクトリを取得できることです。また、さまざまなオプションも使用できます。

第2引数で指定できるオプション

  • GLOB_MARK :各ディレクトリにスラッシュを追加する
  • GLOB_NOSORT:ディレクトリに存在するファイルを返す(ソートはされない)。このフラグを指定しない場合はアルファベット順でソートされる
  • GLOB_NOCHECK:検索パターンにマッチするファイルが見つからない場合、 検索パターン自身を返す
  • GLOB_NOESCAPE:バックスラッシュによるメタ文字のクォートを行わない
  • GLOB_BRACE:{a,b,c} を展開し「a」、「b」あるいは「c」のいずれかにマッチさせる
  • GLOB_ONLYDIR:パターンにマッチするディレクトリのみを返す
  • GLOB_ERR:(ディレクトリが読めないなどの) 読み込みエラー時に停止する。デフォルトではエラーは無視される

使用例

実際にglob関数でワイルドカードを使って任意のファイルやディレクトリを取得してみたいと思います。

環境

使用例を紹介する前に、まずは環境を整理しておきたいと思います。

次のようにルートディレクトリに「smap」「arashi」「tokio」という名前のディレクトリを作成しています。また、その配下に各種のファイルが置かれています。

現在地(プログラム実行ファイルの場所)はルートディレクトリとします。

 【ルートディレクトリ】(現在地)
|
|―【smap】
|  |
|  kimura.html nakai.html inagaki.html
|  kusanagi.php katori.php
|  kimura-takuya.jpg nakai-masahiro.jpg
|  inagaki-gorou.png kusanagi-tuyoshi.png
|  katori-singo.gif
|
|―【arashi】
|  |
|  oono.html sakurai.html aiba.html
|  ninomiya.php matumoto.php
|  oono-satoshi.jpg sakurai-shou.jpg
|  aiba-masaki.png ninomiya-kazuya.png
|  matumoto-jyun.gif
|
|―【tokio】
|  |
|  jyousima.php yamaguti.php
|  kokubun.txt matuoka.txt nagase.txt
|  jyoushima-shigeru.jpg yamaguti-tatuya.jpg
|  kokubun-taiti.png matuoka-masahiro.png
|  nagase-tomoya.gif 

「smap」ディレクトリにあるPHPファイル(.php)を全て取得する

「smap」ディレクトリにあるPHPファイル(.php)を全て取得したい場合、次のようにします。

<?php
//glob関数で指定したファイルを全て取得する
foreach (glob("./smap/*.php") as $file_name){
    //出力
    echo $file_name;
}
?>

これを実行すると次の結果が得られます。

./smap/katori.php
./smap/kusanagi.php

これをみてわかるように取得できるのは「ファイル名」ではなく「ファイルパス」であることに注意してください。

「arashi」ディレクトリにある画像ファイル(.jpg .png .gif)を全て取得する

「arashi」ディレクトリにある画像ファイル(.jpg .png .gif)を全て取得したい場合、次のようにします。

ポイントはglob関数の第2引数にオプション「GLOB_BRACE」を設定していることです。

<?php
//glob関数で指定したファイルを全て取得する
foreach (glob("./arashi/{*.jpg,*.png,*gif}", GLOB_BRACE) as $file_name){
    //出力
    echo $file_name;
}
?>

これを実行すると次の結果が得られます。

./arashi/oono-satoshi.jpg
./arashi/sakurai-shou.jpg
./arashi/aiba-masaki.png
./arashi/ninomiya-kazuya.png
./arashi/matumoto-jyun.gif

1つ下の階層(ディレクトリ)にあるHTMLファイル(.html)を全て取得する

1つ下の階層(例で言うと「smap」「arashi」「tokio」ディレクトリ)にあるHTMLファイル(.html)を全て取得したい場合、次のようにします。

<?php
//glob関数で指定したファイルを全て取得する
foreach (glob("./*/*.html") as $file_name){
    //出力
    echo $file_name;
}
?>

これを実行すると次の結果が得られます。

./arashi/aiba.html
./arashi/oono.html
./arashi/sakurai.html
./smap/inagaki.html
./smap/kimura.html
./smap/nakai.html

1つ下の階層にあるファイルを全て取得する

1つ下の階層にある全てのファイル(拡張子は関係なし)を取得したい場合、次のようにします。

<?php
//glob関数を使って1つ下の階層にあるファイルを全て取得する
foreach(glob("./*/*") as $file_name){
    //出力
    echo $file_name . "<br />";
}
?>

これを実行すると次の結果が得られます。

./arashi/aiba-masaki.png
./arashi/aiba.html
./arashi/matumoto-jyun.gif
./arashi/matumoto.php
./arashi/ninomiya-kazuya.png
./arashi/ninomiya.php
./arashi/oono-satoshi.jpg
./arashi/oono.html
./arashi/sakurai-shou.jpg
./arashi/sakurai.html
./smap/inagaki-gorou.png
./smap/inagaki.html
./smap/katori-singo.gif
./smap/katori.php
./smap/kimura-takuya.jpg
./smap/kimura.html
./smap/kusanagi-tuyoshi.png
./smap/kusanagi.php
./smap/nakai-masahiro.jpg
./smap/nakai.html
./tokio/jyoushima-shigeru.jpg
./tokio/jyousima.php
./tokio/kokubun-taiti.png
./tokio/kokubun.txt
./tokio/matuoka-masahiro.png
./tokio/matuoka.txt
./tokio/nagase-tomoya.gif
./tokio/nagase.txt
./tokio/yamaguti-tatuya.jpg
./tokio/yamaguti.php

PHPファイル以外のファイルを全て取得する

1つ下の階層にあるファイルの中から、PHPファイル(拡張子「.php」をもつファイル)を除外し、それ以外のファイルを全て取得したい場合、次のようにします。

<?php
//glob関数を使って1つ下の階層にあるファイルからPHPファイルを除外する
foreach(glob("./*/*") as $file_name){
    //PHPファイル(拡張子「.php」を持つファイル)は除外したいので
    //「$file_name」が文字列「.php」を持つ場合、次のループに移る(strpos関数で「.php」を検索)
    if(strpos($file_name, ".php")) continue;
   //これ以降はPHPファイル以外のファイルが渡ってくる
   //出力
    echo $file_name . "<br />";
}
?>

これを実行すると、確かにPHPファイル以外のファイルが取得できていることがわかります。

./arashi/aiba-masaki.png
./arashi/aiba.html
./arashi/matumoto-jyun.gif
./arashi/ninomiya-kazuya.png
./arashi/oono-satoshi.jpg
./arashi/oono.html
./arashi/sakurai-shou.jpg
./arashi/sakurai.html
./smap/inagaki-gorou.png
./smap/inagaki.html
./smap/katori-singo.gif
./smap/kimura-takuya.jpg
./smap/kimura.html
./smap/kusanagi-tuyoshi.png
./smap/nakai-masahiro.jpg
./smap/nakai.html
./tokio/jyoushima-shigeru.jpg
./tokio/kokubun-taiti.png
./tokio/kokubun.txt
./tokio/matuoka-masahiro.png
./tokio/matuoka.txt
./tokio/nagase-tomoya.gif
./tokio/nagase.txt
./tokio/yamaguti-tatuya.jpg

希望としてはstrpos関数での文字列検索の方法ではなく、glob関数だけでゴニョゴニョしたかったのですが、軽く調べて感じだと

ワイルドカード:*
文字指定:[ここに指定したい文字]
文字除外指定:[^ここに除外したい文字]

の3つしか使えない感じだったので、上のようなプログラムにしました。

もっと調べたら情報があったかもしれませんが、strpos関数で分岐させたほうが探す手間より楽だったのでこのようにしました。

1つ下の階層で名前に「k」を含むディレクトリを全て取得する

1つ下の階層(ディレクトリ)で名前に「k」を含むディレクトリを全て取得したい場合、次のようにします。

ポイントはglob関数の第2引数にオプション「GLOB_ONLYDIR」を設定していることです。

<?php
//glob関数でディレクトリ名に「k」が含まれるファイルを全て取得する
foreach(glob("./*k*", GLOB_ONLYDIR) as $directory_name){
    //出力
    echo $directory_name;
}
?>

このプログラムを実行すると、次の結果が得られます。

./tokio

 

あわせて読んでほしい!

 

コメント

1:ゆうき:2021/09/01 1:23:50

いつもお世話になっております。

Twitterの一括削除ツールについて、複数の条件を設定して削除しようとすると
「Twitterの仕様が変わった可能性があります。管理人までお知らせください」とメッセージが出てしまいました。

解決方法があれば、ご教授いただけますでしょうか。

よろしくお願いいたします。

コメントフォーム
お名前
コメント