QtのQFileInfo::isHidden()徹底解説:隠しファイルの判定からトラブルシューティングまで

2025-05-31

QFileInfo::isHidden() は、Qt の QFileInfo クラスのメンバー関数の一つです。この関数は、ファイルまたはディレクトリが「隠し(hidden)」属性を持っているかどうかを判定するために使用されます。

戻り値

  • false: ファイルまたはディレクトリが隠しファイル(隠しディレクトリ)ではない場合。
  • true: ファイルまたはディレクトリが隠しファイル(隠しディレクトリ)である場合。

隠しファイルとは

「隠しファイル」の定義は、オペレーティングシステム(OS)によって異なります。

  • Unix系(Linux, macOSなど)

    • ファイル名がピリオド(.)で始まるファイルやディレクトリ(例: .bashrc, .config/)。
    • これらのファイルやディレクトリは、ls コマンドで -a オプションを付けないと通常は表示されません。
    • ファイルの属性として「隠し」が設定されているファイルやフォルダ。
    • 通常、エクスプローラーの設定で「隠しファイル、隠しフォルダー、および隠しドライブを表示する」を有効にしないと表示されません。

QFileInfo::isHidden() は、これらの OS ごとのルールに基づいて、対象のファイルやディレクトリが隠し属性を持っているかどうかを自動的に判断してくれます。

使用例

#include <QCoreApplication>
#include <QFileInfo>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 例1: 隠しファイル(Unix系の場合)
    // Windowsの場合、C:\Users\YourUser\AppData など、隠し属性を持つパスを指定してください
    QFileInfo hiddenFile(".my_hidden_file"); // Unix系の場合の隠しファイル名
    if (hiddenFile.isHidden()) {
        qDebug() << hiddenFile.fileName() << "は隠しファイルです。";
    } else {
        qDebug() << hiddenFile.fileName() << "は隠しファイルではありません。";
    }

    // 例2: 通常のファイル
    QFileInfo normalFile("normal_file.txt");
    if (normalFile.isHidden()) {
        qDebug() << normalFile.fileName() << "は隠しファイルです。";
    } else {
        qDebug() << normalFile.fileName() << "は隠しファイルではありません。";
    }

    // 例3: 隠しディレクトリ(Unix系の場合)
    QFileInfo hiddenDir(".my_hidden_dir"); // Unix系の場合の隠しディレクトリ名
    if (hiddenDir.isDir() && hiddenDir.isHidden()) {
        qDebug() << hiddenDir.fileName() << "は隠しディレクトリです。";
    } else {
        qDebug() << hiddenDir.fileName() << "は隠しディレクトリではありません。";
    }

    return a.exec();
}

コンパイルと実行の注意点

  • このコードを実行する前に、テスト用の隠しファイルや通常のファイルを作成しておくと、より正確な結果を確認できます。
    • Unix系の場合:touch .my_hidden_filemkdir .my_hidden_dir
    • Windowsの場合:エクスプローラーでファイル/フォルダのプロパティから「隠しファイル」属性を設定するか、attrib +h my_hidden_file.txt などのコマンドを使用します。


QFileInfo::isHidden() 自体は非常にシンプルな関数であり、直接的なエラーが発生することは稀です。しかし、その利用方法や前提条件によって、期待通りの結果が得られない場合があります。

エラー:常に false が返される(隠しファイルなのに隠しと判定されない)

原因とトラブルシューティング

  • シンボリックリンクの扱い

    • 原因
      QFileInfo はデフォルトでシンボリックリンク自体を扱います。もしシンボリックリンクが隠し属性を持っていないが、そのリンク先が隠しである場合、isHidden()false を返します。
    • トラブルシューティング
      シンボリックリンクのリンク先の情報を取得したい場合は、QFileInfo::symLinkTarget() でリンク先のパスを取得し、そのパスで新しい QFileInfo オブジェクトを作成して isHidden() を呼び出す必要があります。
    • コード例
      QFileInfo symlinkInfo("path/to/my_symlink");
      if (symlinkInfo.isSymLink()) {
          QString targetPath = symlinkInfo.symLinkTarget();
          QFileInfo targetInfo(targetPath);
          if (targetInfo.exists() && targetInfo.isHidden()) {
              qDebug() << symlinkInfo.fileName() << "のリンク先" << targetInfo.fileName() << "は隠しファイルです。";
          }
      } else if (symlinkInfo.isHidden()) {
          qDebug() << symlinkInfo.fileName() << "は隠しファイルです。";
      }
      
  • パスの指定ミスまたはファイルが存在しない

    • 原因
      QFileInfo のコンストラクタに渡されたパスが間違っている、またはそのパスにファイル/ディレクトリが存在しない場合。QFileInfo はファイルが存在しない場合でもオブジェクトを作成できますが、isHidden() は当然ながら意味のある値を返しません(通常は false を返します)。
    • トラブルシューティング
      • QFileInfo::exists() を使用して、まずファイルやディレクトリが実際に存在するかどうかを確認してください。
      • 絶対パスと相対パスのどちらで指定しているかを確認し、実行時のカレントディレクトリと相対パスの整合性を確認してください。
    • コード例
      QFileInfo fileInfo("path/to/my_file.txt");
      if (!fileInfo.exists()) {
          qWarning() << fileInfo.filePath() << "は存在しません。";
          // 処理を中断するか、別のエラーハンドリングを行う
          return;
      }
      if (fileInfo.isHidden()) {
          // ...
      }
      
    • 原因
      Windows の「隠しファイル属性」と Unix 系(Linux, macOS)の「ファイル名が . で始まる」というルールを混同している。
    • トラブルシューティング
      • Windows の場合
        対象のファイルまたはフォルダが、本当に Windows のエクスプローラーで「隠し」属性が設定されているか確認してください。ファイル名の先頭に . を付けても、Windows では隠しファイルにはなりません。
      • Unix 系の場合
        ファイル名がピリオド(.)で始まっていることを確認してください。ファイル属性として「隠し」を設定する概念は通常ありません。
    • 確認方法
      • Windows: ファイル/フォルダを右クリックし、「プロパティ」を開き、「隠しファイル」チェックボックスを確認。
      • Unix系: ターミナルで ls -a コマンドを実行し、対象のファイル名が . で始まっているか確認。

エラー:パーミッションの問題で情報が取得できない

原因とトラブルシューティング

  • アクセス権限の不足
    • 原因
      QFileInfo はファイルシステムにアクセスして情報を取得するため、対象のファイルやディレクトリへの読み取り権限がない場合、正しい情報を取得できないことがあります。
    • トラブルシューティング
      プログラムを実行しているユーザーアカウントが、対象のファイルまたはディレクトリにアクセスする権限を持っているか確認してください。特に、共有フォルダやシステムファイルなどでは注意が必要です。
    • 確認方法
      OS のファイルシステム設定で、該当ファイル/フォルダのパーミッションを確認します。必要であれば、プログラムを管理者権限(Windows)または sudo(Unix系)で実行してみることで、権限の問題であるかどうかの切り分けができます。(ただし、本番運用では最小限の権限で実行することが推奨されます。)

潜在的な問題:パフォーマンスへの影響

isHidden() 自体がパフォーマンスボトルネックになることは稀ですが、大量のファイルに対してループ内で頻繁に呼び出す場合、ファイルシステムへのI/Oが発生するため、わずかながら影響が出る可能性があります。

トラブルシューティング

  • 特に必要がなければ、不要なファイルシステムアクセスは避けるように設計を検討してください。例えば、ファイルリストを一度に取得し、そのリストに対して処理を行うなど。

QFileInfo::isHidden() で問題が発生する場合、ほとんどは以下のいずれかが原因です。

  1. OSごとの「隠し」の定義の誤解
  2. パスの誤りやファイル/ディレクトリの非存在
  3. パーミッション不足
  4. シンボリックリンクの扱いに関する誤解


例1:単一のファイルやディレクトリの隠し属性をチェックする

これは最も基本的な使用例です。指定されたパスが隠しファイル/ディレクトリであるかどうかを判定します。

#include <QCoreApplication>
#include <QFileInfo>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // --- Windows 環境での例 ---
    // 隠し属性を持つファイルを作成 (手動で作成するか、プログラムでattribコマンドを使用)
    // 例: C:\Temp\hidden_file.txt を「隠し」属性に設定
    // 例: C:\Users\YourUser\AppData (通常は隠しフォルダ)
    QFileInfo winHiddenFile("C:/Temp/hidden_file.txt"); // 存在しない場合はfalseを返す
    QFileInfo winAppdataDir("C:/Users/YourUser/AppData"); // お使いのユーザー名に置き換えてください

    qDebug() << "--- Windows の例 ---";
    if (winHiddenFile.exists()) {
        qDebug() << winHiddenFile.fileName() << "が存在します。隠し属性は:" << winHiddenFile.isHidden();
    } else {
        qDebug() << winHiddenFile.fileName() << "は存在しません。";
    }

    if (winAppdataDir.exists()) {
        qDebug() << winAppdataDir.fileName() << "が存在します。隠し属性は:" << winAppdataDir.isHidden();
    } else {
        qDebug() << winAppdataDir.fileName() << "は存在しません。";
    }

    // --- Unix 系 (Linux/macOS) 環境での例 ---
    // ファイル名の先頭に '.' を付けることで隠しファイルになる
    QFileInfo unixHiddenFile(".my_secret_config");
    QFileInfo unixNormalFile("document.txt");
    QFileInfo unixHiddenDir(".cache");

    // テスト用にファイルを作成
    // system("touch .my_secret_config");
    // system("touch document.txt");
    // system("mkdir .cache");

    qDebug() << "\n--- Unix 系の例 ---";
    if (unixHiddenFile.exists()) {
        qDebug() << unixHiddenFile.fileName() << "が存在します。隠し属性は:" << unixHiddenFile.isHidden();
    } else {
        qDebug() << unixHiddenFile.fileName() << "は存在しません。(テスト用に作成してみてください)";
    }

    if (unixNormalFile.exists()) {
        qDebug() << unixNormalFile.fileName() << "が存在します。隠し属性は:" << unixNormalFile.isHidden();
    } else {
        qDebug() << unixNormalFile.fileName() << "は存在しません。(テスト用に作成してみてください)";
    }

    if (unixHiddenDir.exists() && unixHiddenDir.isDir()) {
        qDebug() << unixHiddenDir.fileName() << "が存在します。隠し属性は:" << unixHiddenDir.isHidden();
    } else {
        qDebug() << unixHiddenDir.fileName() << "は存在しません。(テスト用に作成してみてください)";
    }

    return a.exec();
}

実行前の準備

  • Unix 系 (Linux/macOS)
    実行するディレクトリで、ターミナルから touch .my_secret_configtouch document.txtmkdir .cache を実行してテストファイル/ディレクトリを作成してください。
  • Windows
    C:\Temp フォルダを作成し、その中に hidden_file.txt を作成します。その後、エクスプローラーで hidden_file.txt を右クリック -> プロパティ -> 属性 -> 「隠しファイル」にチェックを入れて適用します。C:\Users\YourUser\AppData は通常デフォルトで隠し属性を持っています。

例2:ディレクトリ内の隠しファイル/ディレクトリをリストアップする

特定のディレクトリ内にある隠しファイルや隠しディレクトリを検索して表示する例です。

#include <QCoreApplication>
#include <QDir>
#include <QFileInfo>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QString targetDirPath = QDir::currentPath(); // 現在のディレクトリを対象とする
    // あるいは特定のパスを指定:
    // QString targetDirPath = "C:/Users/YourUser"; // Windows
    // QString targetDirPath = "/home/youruser"; // Linux

    QDir targetDir(targetDirPath);

    if (!targetDir.exists()) {
        qDebug() << "ディレクトリが見つかりません:" << targetDirPath;
        return 1;
    }

    qDebug() << targetDirPath << "内の隠しファイル/ディレクトリを検索中...";

    // ディレクトリ内のすべてのエントリを取得 (隠しファイルも含む)
    // QDir::AllEntries: ファイル、ディレクトリ、シンボリックリンクなどすべて
    // QDir::NoDotAndDotDot: '.' と '..' を除外
    QFileInfoList entries = targetDir.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System, QDir::Name);

    if (entries.isEmpty()) {
        qDebug() << "隠しファイル/ディレクトリは見つかりませんでした。";
    } else {
        qDebug() << "見つかった隠しファイル/ディレクトリ:";
        for (const QFileInfo &fileInfo : entries) {
            // isHidden() を使って隠し属性かどうかを判定
            // QDir::Hidden フラグを使っているため、isDir() や isFile() で絞り込むと良いでしょう。
            if (fileInfo.isHidden()) {
                QString type = fileInfo.isDir() ? "ディレクトリ" : "ファイル";
                qDebug() << "  - " << fileInfo.fileName() << " (" << type << ")";
            }
        }
    }

    return a.exec();
}

解説

  • その後、ループで各 QFileInfo オブジェクトに対して isHidden() を呼び出し、明示的に隠し属性を持つものを特定しています。QDir::System フラグも指定すると、システムファイルも含まれることがあります。
  • QDir::entryInfoList()QDir::Hidden フラグを含めることで、隠しファイルもリストに含まれるようになります。

例3:特定の拡張子の隠しファイルのみを処理する

隠しファイルの中でも、特定の拡張子を持つものだけを対象とする例です。

#include <QCoreApplication>
#include <QDir>
#include <QFileInfo>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QString targetDirPath = QDir::currentPath();
    QDir targetDir(targetDirPath);

    if (!targetDir.exists()) {
        qDebug() << "ディレクトリが見つかりません:" << targetDirPath;
        return 1;
    }

    QStringList desiredSuffixes;
    desiredSuffixes << "log" << "conf" << "tmp"; // 処理したい隠しファイルの拡張子

    qDebug() << targetDirPath << "内の隠しファイルで、拡張子が" << desiredSuffixes.join(", ") << "のものを検索中...";

    QFileInfoList entries = targetDir.entryInfoList(QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot, QDir::Name);

    if (entries.isEmpty()) {
        qDebug() << "条件に合う隠しファイルは見つかりませんでした。";
    } else {
        qDebug() << "見つかったファイル:";
        for (const QFileInfo &fileInfo : entries) {
            if (fileInfo.isHidden() && desiredSuffixes.contains(fileInfo.suffix().toLower())) {
                qDebug() << "  - 処理対象:" << fileInfo.fileName() << " (パス:" << fileInfo.filePath() << ")";
                // ここで隠しファイルの処理を行う
                // 例: ファイルの内容を読み込む、ログを解析するなど
            }
        }
    }

    return a.exec();
}
  • Windowsの場合: test.log というファイルを作成し、隠し属性を付けてください。
  • Unix系の場合: touch .mylog.log, touch .config.conf, touch .temp.tmp などのファイルを作成してテストします。


しかし、**「代替手段」**を考える場合、それは通常、以下のような状況で検討されます。