空腹おやじのログと備忘録

VBA(主にExcel)でいろいろな実験的な事とか、Linuxのコマンドとか設定とかについて忘れないように、あれこれと・・・

【C++】フォルダ内のファイル一覧取得(エクスプローラー風ソート)

前置き

C++で、FindFirstFileEx を使って、ファイルを取得。
エクスプローラー風に、数字が綺麗に昇順になるようにソートする。
サブフォルダは、除外。

コード

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <Windows.h>
#include <shlwapi.h>    //StrCmpLogicalW

#pragma comment(lib,"Shlwapi.lib")

using namespace std;

int main()
{
    //wcin の文字化け対策
    ios_base::sync_with_stdio(false);
    wcin.imbue(locale("japanese"));

    wcout << L"Input target Folder:";

    wstring sTargetFolder;
    getline(wcin, sTargetFolder);

    if (!sTargetFolder.size())
    {
        wcout << L"Not entered.\n";

        return 0;
    }

    //スペース等を含んだパスのような場合の前後のダブルクォーテーションを除去
    if ((sTargetFolder.substr(0, 1) == L"\"") &&
        (sTargetFolder.substr(sTargetFolder.size() - 1, 1) == L"\""))
        sTargetFolder = sTargetFolder.substr(1, sTargetFolder.size() - 2);

    //パスの末尾が "\" でない場合、"\" を付加
    if (sTargetFolder.substr(sTargetFolder.size() - 1) != L"\\")
        sTargetFolder += L"\\";

    //全ファイルを対象
    sTargetFolder += L"*";

    WIN32_FIND_DATA fd;
    HANDLE hFind = FindFirstFileExW(
        sTargetFolder.c_str(),
        FindExInfoBasic,
        &fd,
        FindExSearchNameMatch,
        nullptr,
        FIND_FIRST_EX_LARGE_FETCH);

    if (hFind == INVALID_HANDLE_VALUE)
    {
        wcout << L"Target not found.\n";

        return 0;
    }

    vector<wstring> vFiles;

    do
    {
        //フォルダは除外
        if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
            continue;

        vFiles.push_back(fd.cFileName);
    } while (FindNextFileW(hFind, &fd));

    FindClose(hFind);

    //エクスプローラー風のソート
    sort(vFiles.begin(),
        vFiles.end(),
        [](const wstring& ws1, const wstring& ws2)
    {
        return StrCmpLogicalW(ws1.c_str(), ws2.c_str()) < 0;
    });

    for (const auto& v : vFiles)
        wcout << v << L"\n";

    return 0;
}

実行結果

検索対象ファイル
f:id:Z1000S:20200625222525p:plain

実行
f:id:Z1000S:20200625222715p:plain

通常のソートを使用した場合

sort(vFiles.begin(), vFiles.end());

f:id:Z1000S:20200625222844p:plain

気が向いたら、再帰して、サブフォルダも処理するやつを作るかもしれない・・・
(作りそうな気がする・・・)

参考

VBAで、FindFirstFile (Ex でないやつ)を使ったやつ
z1000s.hatenablog.com

上の記事ので紹介している記事の発展版。
VBAで、FindFirstFileEx を使ってやってるので、興味がある方はどうぞ。
www.excel-chunchun.com

sort を参考に(パクリとも言う)させていただきました。m(_ _)m
suzulang.com