ディレクトリの存在を確認し、存在しない場合は作成します


388

多くの場合、多くの出力を生成するRスクリプトを作成しています。この出力を独自のディレクトリに配置する方がわかりやすいと思います。以下に書いたものは、ディレクトリの存在を確認してそこに移動するか、ディレクトリを作成してそこに移動します。これに取り組むより良い方法はありますか?

mainDir <- "c:/path/to/main/dir"
subDir <- "outputDirectory"

if (file.exists(subDir)){
    setwd(file.path(mainDir, subDir))
} else {
    dir.create(file.path(mainDir, subDir))
    setwd(file.path(mainDir, subDir))

}

1
ランダムに生成された名前で一時ディレクトリを作成し、その名前を返すR関数を見たことがあると思います。一時ファイルを作成する同様のものがあると思います。それらをすぐに見つけることはできませんが、Databelパッケージ(cran.r-project.org/web/packages/DatABEL/index.html)には関数get_temporary_file_nameがあります。
PaulHurleyuk 2010年

42
setwd()Rコードでは決して使用しないでください。コードをコンピューター間で簡単に移動することができなくなるため、基本的には作業ディレクトリーを使用するという考えに反します。
ハドリーは2010年

6
@hadleyを熟考する興味深いトピックです。同じ目的で他の方法についてのあなたの考えをいただければ幸いです。職場では、すべてのコンピューターが同じネットワークに同期されているため、ファイルパスは一貫しています。そうでない場合、スクリプトの移植性よりも対処すべき大きな問題があります。この特定の例では、私たちの国立公園を2年間持ち歩くマシンにロードされるスクリプトを書いていました。このスクリプトは、ローカルSQLインスタンスからデータを取得し、いくつかの処理を実行して、.csvを吐き出します。最終製品は.bat、エンドユーザーが変更する必要のないファイルになります。
2010年

@Chaseしかしsetwd、ネットワークパスを操作する必要はありません。結果を保存し、現在のパス(Rセッションの開始時に確立されたパス)を操作するためのパスを指定するだけです。または、希望の作業ディレクトリでRを起動します。
Marek

5
うん。または、パラメータ化out_dir <- "path/to/output/directory"してから使用してくださいwrite.table(file = file.path(out_dir,"table_1.csv"), ...)。またはそれout_file <- function(fnm) file.path("path/to/output/directory", fnm)からwrite.table(file = out_file("table_1.csv"), ...)(ネットワークドライブを操作するときに使用する同様の方法)。
Marek

回答:


403

使用showWarnings = FALSE

dir.create(file.path(mainDir, subDir), showWarnings = FALSE)
setwd(file.path(mainDir, subDir))

dir.create()ディレクトリがすでに存在する場合はクラッシュせず、警告が出力されるだけです。したがって、警告が表示されても問題がなければ、これを行うだけで問題はありません。

dir.create(file.path(mainDir, subDir))
setwd(file.path(mainDir, subDir))

58
showWarnings = FALSEこれを使用すると、ディレクトリが作成できないなどの他の警告も非表示になることに注意してください。
zelanix 2014年

5
^特定の警告を1つだけ抑制する方法はありますか?
Bas

2
こんにちは、私はフォルダtest1にいる場合のようにネストされたディレクトリを作成したいのですが、test2の内部test2の内部... ...しかし、今は問題に直面しています。directory1が存在しない場合でも、3レベルのディレクトリを作成する方法はありますか?
Praveen Kesani

10
@PraveenKesaniこれはあなたが探しているものですdir.create("test1/test2/test3/", recursive=TRUE)か?
ディーン。

6
@Bas本当に遅い応答ですが、suppressWarnings(<statement>)そのステートメントだけの警告は抑制されます。
Ram RS

163

2015年4月16日のリリースに伴い、R 3.2.0という新しい関数がありdir.exists()ます。この関数を使用して、ディレクトリが存在しない場合に作成するには、次のコマンドを使用できます。

ifelse(!dir.exists(file.path(mainDir, subDir)), dir.create(file.path(mainDir, subDir)), FALSE)

これはFALSE、ディレクトリがすでに存在するかTRUE作成できない場合、および存在しなかったが正常に作成された場合に返されます。

単にディレクトリが存在するかどうかを確認するには、次のように使用できます

dir.exists(file.path(mainDir, subDir))

9
ifelse()ベクトル化されていない分岐に使用することはお勧めできません。
Lionel Henry

2
@Basは、コード化された何かが起こっているかのようにコードが誤って読み取られるためです。|スカラーの代わりにベクトル化を使用するようなもの||です。それは機能しますが、悪い習慣です。
Lionel Henry

1
ああ、いまいましいので、を使用してifステートメントも間違っています|が、ベクトル化が||時々機能しない理由は何ですか?私はこれがトピックから外れていることを知っていますが、私はそれを見つけるのが熱心すぎます。ベクトル化について詳しく説明します。ありがとう
Bas

4
それで、私たちが避けなければならない場合、これを行うための最良の方法はifelse何ですか?
KillerSnail

6
ifとelseを使用;)
ライオネルヘンリー

17

一般的なアーキテクチャの観点から、ディレクトリの作成に関しては、次の構造をお勧めします。これはほとんどの潜在的な問題をカバーし、ディレクトリ作成に関するその他の問題はdir.create呼び出しによって検出されます。

mainDir <- "~"
subDir <- "outputDirectory"

if (file.exists(paste(mainDir, subDir, "/", sep = "/", collapse = "/"))) {
    cat("subDir exists in mainDir and is a directory")
} else if (file.exists(paste(mainDir, subDir, sep = "/", collapse = "/"))) {
    cat("subDir exists in mainDir but is a file")
    # you will probably want to handle this separately
} else {
    cat("subDir does not exist in mainDir - creating")
    dir.create(file.path(mainDir, subDir))
}

if (file.exists(paste(mainDir, subDir, "/", sep = "/", collapse = "/"))) {
    # By this point, the directory either existed or has been successfully created
    setwd(file.path(mainDir, subDir))
} else {
    cat("subDir does not exist")
    # Handle this error as appropriate
}

また、が~/foo存在しない場合、dir.create('~/foo/bar')を指定しない限り、への呼び出しは失敗しますrecursive = TRUE


3
paste(...)とfile.path(mainDir、subDir)を使用する理由はありますか?また、path <-file.path(mainDir、subDir)を実行した場合、ifステートメントを読みやすくするために5回再利用できます。
MikeF

14

以下は簡単なチェックで存在しない場合はdirを作成します。

## Provide the dir name(i.e sub dir) that you want to create under main dir:
output_dir <- file.path(main_dir, sub_dir)

if (!dir.exists(output_dir)){
dir.create(output_dir)
} else {
    print("Dir already exists!")
}

9

file.exists()を使用してディレクトリの存在をテストすることは、元の投稿の問題です。subDirにパスではなく既存のファイルの名前が含まれている場合、file.exists()はTRUEを返しますが、作業ディレクトリをファイルを指すように設定できないため、setwd()の呼び出しは失敗します。

file_test(op = "-d"、subDir)の使用をお勧めします。これは、subDirが既存のディレクトリの場合は "TRUE"を返しますが、subDirが既存のファイルまたは存在しないファイルまたはディレクトリの場合はFALSEを返します。同様に、ファイルのチェックはop = "-f"で実行できます。

さらに、別のコメントで説明されているように、作業ディレクトリはR環境の一部であり、スクリプトではなくユーザーが制御する必要があります。スクリプトは、R環境を変更しないことが理想的です。この問題に対処するには、options()を使用して、すべての出力が必要なグローバルに利用可能なディレクトリを保存します。

したがって、someUniqueTagがプログラマーが定義したオプション名の接頭辞である次のソリューションを検討してください。これにより、同じ名前のオプションがすでに存在する可能性は低くなります。(たとえば、「filer」というパッケージを開発している場合は、filer.mainDirとfiler.subDirを使用できます)。

次のコードを使用して、後で他のスクリプトで使用できるオプションを設定し(したがって、スクリプトでsetwd()を使用しないようにし)、必要に応じてフォルダーを作成します。

mainDir = "c:/path/to/main/dir"
subDir = "outputDirectory"

options(someUniqueTag.mainDir = mainDir)
options(someUniqueTag.subDir = "subDir")

if (!file_test("-d", file.path(mainDir, subDir)){
  if(file_test("-f", file.path(mainDir, subDir)) {
    stop("Path can't be created because a file with that name already exists.")
  } else {
    dir.create(file.path(mainDir, subDir))
  }
}

次に、subDirのファイルを操作する必要がある後続のスクリプトで、次のようなものを使用します。

mainDir = getOption(someUniqueTag.mainDir)
subDir = getOption(someUniqueTag.subDir)
filename = "fileToBeCreated.txt"
file.create(file.path(mainDir, subDir, filename))

このソリューションでは、作業ディレクトリがユーザーの制御下に置かれます。


8

R 2.15.3で問題がありました。共有ネットワークドライブでツリー構造を再帰的に作成しようとすると、アクセス許可エラーが発生しました。

この奇妙さを回避するために、手動で構造を作成します。

mkdirs <- function(fp) {
    if(!file.exists(fp)) {
        mkdirs(dirname(fp))
        dir.create(fp)
    }
} 

mkdirs("H:/foo/bar")

5

一発ギャグ:

if (!dir.exists(output_dir)) {dir.create(output_dir)}

例:

dateDIR <- as.character(Sys.Date())
outputDIR <- file.path(outD, dateDIR)
if (!dir.exists(outputDIR)) {dir.create(outputDIR)}

2

パスが有効なディレクトリであるかどうかを確認するには、次のようにしてください。

file.info(cacheDir)[1,"isdir"]

file.info 最後のスラッシュは気にしません。

file.existsWindowsでは、ディレクトリがスラッシュで終わっている場合、そのディレクトリで失敗し、スラッシュなしで成功します。したがって、これはパスがディレクトリかどうかを判断するために使用することはできません。

file.exists("R:/data/CCAM/CCAMC160b_echam5_A2-ct-uf.-5t05N.190to240E_level1000/cache/")
[1] FALSE

file.exists("R:/data/CCAM/CCAMC160b_echam5_A2-ct-uf.-5t05N.190to240E_level1000/cache")
[1] TRUE

file.info(cacheDir)["isdir"]

この回答の何が問題になっていdir.create()ますか?記述が間違っているか、それとも手元の質問を解決するのに役立たないと考えられていますか?
mschilli
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.