web-dev-qa-db-ja.com

Unixにディレクトリが存在するかどうかを確認する(システムコール)

問題の解決策をオンラインで見つけることができません。

Unixで関数を呼び出し、ディレクトリのパスを渡し、存在するかどうかを知りたいです。 opendir()は、ディレクトリが存在しない場合はエラーを返しますが、私の目標は、実際に開いてエラーを確認し、エラーがなければ閉じて、ファイルがディレクトリかどうかを確認することです。

それを行う便利な方法はありますか?

49
Jary

POSIXシステムには、2つの関連する関数があります: stat()およびlstat() 。これらは、パス名が実際にアクセスする権限を持っているオブジェクトを参照しているかどうかを調べるために使用されます。参照している場合、返されるデータはオブジェクトのタイプを示します。 stat()lstat()の違いは、指定した名前がシンボリックリンクである場合、stat()はシンボリックリンク(または、チェーンでつながれている場合はリンク)に従うことです。 lstat()はシンボリックリンク自体について報告しますが、リンクチェーンの最後にあるオブジェクトについて報告します。

#include <sys/stat.h>

struct stat sb;

if (stat(pathname, &sb) == 0 && S_ISDIR(sb.st_mode))
{
    ...it is a directory...
}

関数が成功したことを示している場合、 <sys/stat.h> のS_ISDIR()マクロを使用して、ファイルが実際にディレクトリであるかどうかを判断します。

他のS_IS*マクロを使用して、他のファイルタイプを確認することもできます。

  • S_ISDIR —ディレクトリ
  • S_ISREG —通常のファイル
  • S_ISCHR —キャラクターデバイス
  • S_ISBLK —ブロックデバイス
  • S_ISFIFO — FIFO
  • S_ISLNK —シンボリックリンク
  • S_ISSOCK —ソケット

(他のいくつかのファイルタイプも提供するシステムもあります。たとえば、S_ISDOORはSolarisで利用可能です。)

105

stat システムコールを使用するには、最初の引数としてディレクトリの名前を渡します。ディレクトリが存在する場合は0が返され、そうでない場合は-1が返され、errnoはENOENTに設定されます

編集:

戻り値が0である場合、引数が実際にディレクトリであり、file/symlink/char特殊ファイル/ blk特殊ファイル/ FIFOファイルではないことを確認するための追加チェックが必要になります。これには st_modestat structureフィールドを使用できます。

5
codaddict

シェルから話している場合、良いSO answer here。 その答えを要約すると:

_if [ -d "$DIRECTORY" ]; then
    # Control will enter here if $DIRECTORY exists
fi
_

Cプログラムの内部から話している場合は、 stat() を使用できます。

_{
    struct stat st;
    if(stat("/tmp",&st) == 0)
        printf(" /tmp is present\n");
}
_
3
Bryan

test -dを使用できます

3
chigley

別の簡単な方法は次のとおりです。

int check(unsigned const char type) {
    if(type == DT_REG)
        return 1;
    if(type == DT_DIR)
        return 0;
    return -1;
}

次に、struct dirent *オブジェクトのd_typeをcheck関数に渡すことができます。

Checkが1を返す場合、そのパスは通常のファイルを指します。

Checkが0を返す場合、そのパスはディレクトリを指します。

それ以外の場合は、ファイルでもディレクトリでもありません(ブロックデバイス/シンボリックリンクなどが可能です)。

1

テスト済みで正常に動作しています:

int file_exist (char *filename)
{
    char s[200];
    sprintf(s, "test -e %s", filename);
    if (system(s) == 0){
        return 1;
    }else{
        return 0;
    }
}
1
Mehrdad Seyrafi

このファイルシステムオブジェクトのタイプをあまり気にしない場合、access(name、F_OK)はこの名前を持つ何かの存在をチェックします。これがディレクトリであることを確認する必要がある場合は、stat()を使用し、S_ISDIR()マクロでタイプをチェックします。

1
blaze

関数statはあなたが望むことをするかもしれないと思います(ディレクトリのテストはしていません)。 C++では、boost :: filesystemライブラリも使用できます。

0
neodelphi