2007年9月19日水曜日

ファイルの情報を規則に従ってソート

SQLele利用スクリプト第3弾。
今まで書きためたスクリプト(拡張子.hspのファイル)の一覧を作成し、「更新年月日ランキング」「サイズランキング」「ファイル名の長さランキング」を決定します。今までの蓄積が分かって面白いかもしれません。

ファイルの検索にdirlist2を、データベースの作成にcsvstrを利用しています。
場合によってはdirlist2で得た結果をそのままINSERT 文に渡しても良いでしょう。

SQL文はソートをORDER BYで指定することと、昇順はASC,降順はDESCで指定することさえ理解できれば特に難しいことはしていません。また、LIMITを指定することで特定数のファイルのみを取得しています。

フルパスじゃないのにカラム名をFULLPATHとしていた点を修正。(2007/09/20)
SQLele1.1リリースに合わせ、ファイル名の長さを「bytes」から「文字」に変更。(2007/09/29)

#include "sqlele.hsp"
#include "hspext.as"
#include "hspda.as"
#const RANKING_NUM  5                   // ランキングのTOPいくつまでを表示するか?

// 検索するフォルダを取得し、カレントディレクトリとする
    sdim target_folder, 1024
    selfolder target_folder, ""
    chdir target_folder

// カレントディレクトリ以下にあるファイルをdirlist2で検索
// ファイルのフルパス・サイズ・更新日付を取得する
// カンマ区切りで記録されるため、csvstr命令で分解することが可能
    dirlist2h %1101
    dirlist2 var_size, "*.hsp"%01    // サブディレクトリも検索
    if ( stat < RANKING_NUM ) {
        // ファイルが少なすぎる
        dialog "ファイルが少なすぎます。"1
        end
    }
    title strstat ) + "個のファイルが見つかりました。"
    sdim files, var_size + 1
    dirlist2r files

// メモリ上にデータベース作成
// 必要ないので、主キーは作成しない
    sql_open ":memory:"
    sql_q "CREATE TABLE FILES (PATH,FILENAME,FILESIZE,TIMESTAMP)"
    notesel files                       // 先ほどの検索結果をメモリノートパッド命令のバッファに設定
    sdim tmp_line, 1024                 // メモリノートパッドから取り出した行を格納する変数
    sdim tmp_cells, 2563              // 行を変換(分解)した結果を格納する配列変数

    sql_q "BEGIN"                       // トランザクションの開始
    repeat notemax
        noteget tmp_line, cnt               // 1行ずつ取り出す(getstrを使えば、より高速化可能)
        csvstr tmp_cells, tmp_line          // 取り出した行を配列に変換
        file_name = getpath( tmp_cells( 0 ), 8 )
        sql_q "INSERT INTO FILES VALUES (" + prm_text(tmp_cells(0)) + ", " + prm_text(file_name) + ", " + prm_i(int(tmp_cells(1))) + ", " + prm_text(tmp_cells(2)) + ")"
    loop
    sql_q "COMMIT"                      // トランザクションの終了

// ランキングの集計
// SELECT 文の ORDER BY を利用することによって実現
// サブルーチンなどでよりスマートにできるはず……。
    result = ""                         // 結果を格納する変数

    // ファイルサイズランキング(大きい順)
    sql_q "SELECT PATH,FILESIZE FROM FILES ORDER BY FILESIZE DESC LIMIT " + RANKING_NUM
    repeat RANKING_NUM1
        result += strcnt ) + "番目に大きいファイルは" + sql_v"PATH" ) + "(" + sql_v"FILESIZE" ) + "bytes)です。\n"
        sql_next
    loop
    result += "----\n"

    // ファイルサイズランキング(小さい順)
    sql_q "SELECT PATH,FILESIZE FROM FILES ORDER BY FILESIZE ASC LIMIT " + RANKING_NUM
    repeat RANKING_NUM1
        result += strcnt ) + "番目に小さいファイルは" + sql_v"PATH" ) + "(" + sql_v"FILESIZE" ) + "bytes)です。\n"
        sql_next
    loop
    result += "----\n"

    // 更新年月日ランキング(新しい順)
    sql_q "SELECT PATH,TIMESTAMP FROM FILES ORDER BY TIMESTAMP DESC LIMIT " + RANKING_NUM
    repeat RANKING_NUM1
        result += strcnt ) + "番目に新しいファイルは" + sql_v"PATH" ) + "(" + sql_v"TIMESTAMP" ) + ")です。\n"
        sql_next
    loop
    result += "----\n"

    // 更新年月日ランキング(古い順)
    sql_q "SELECT PATH,TIMESTAMP FROM FILES ORDER BY TIMESTAMP ASC LIMIT " + RANKING_NUM
    repeat RANKING_NUM1
        result += strcnt ) + "番目に古いファイルは" + sql_v"PATH" ) + "(" + sql_v"TIMESTAMP" ) + ")です。\n"
        sql_next
    loop
    result += "----\n"

    // ファイル名の長さランキング(長い順)
    sql_q "SELECT PATH,length(FILENAME) AS LENGTH FROM FILES ORDER BY LENGTH DESC LIMIT " + RANKING_NUM
    repeat RANKING_NUM1
        result += strcnt ) + "番目に名前の長いファイルは" + sql_v"PATH" ) + "(" + sql_v"LENGTH" ) + "文字)です。\n"
        sql_next
    loop
    result += "----\n"

    // ファイル名の長さランキング(短い順)
    sql_q "SELECT PATH,length(FILENAME) AS LENGTH FROM FILES ORDER BY LENGTH ASC LIMIT " + RANKING_NUM
    repeat RANKING_NUM1
        result += strcnt ) + "番目に名前の短いファイルは" + sql_v"PATH" ) + "(" + sql_v"LENGTH" ) + "文字)です。\n"
        sql_next
    loop

// データベースを閉じ、結果を表示
    sql_close
    mesbox result, ginfo_winxginfo_winy4
    stop

4 件のコメント:

FUJI さんのコメント...

おおー面白いですね。
SQLele 、色々面白そうなことが出来そうでわくわくします。

ところで実行結果を見ると、ファイル名の長さは bytes と書かれてありますが実際はバイト単位ではなく文字数のようです。

eller さんのコメント...

fujiさん、お久しぶりです。SQLeleはホントにいろんな事ができて面白いですよ。
fujiさんもぜひ使ってみてください。

>実際はバイト単位ではなく文字数のようです。
おや、そうでしたか?手元の環境では間違いなくバイトで返ってきている(日本語は2バイトと数えている)のですが……。

fuji さんのコメント...

>fujiさんもぜひ使ってみてください。
ぜひ使ってみたいと思っています。

>おや、そうでしたか?手元の環境では間違いなくバイトで返ってきている(日本語は2バイトと数えている)のですが……。
すいません、勘違いでした。もう一度確かめたらバイト単位でした。失礼しました。

eller さんのコメント...

環境によって動作が違うのかなと少し不安でしたが、そうではなかったようで安心しました。
まぁSQLele1.1からUTF-8での保存になるそうなので、そうなればShift-JISのbytesとは違くなるのでしょうけど。