Rの関数dirとfile.copyの引数recursiveの挙動を確認します。
関数 dir
Rの dir 関数(および内部で呼び出されている list.files 関数)における recursive 引数について確認します。
引数 recursive は「サブフォルダ(下層のディレクトリ)の中まで再帰的に探すかどうか」を指定する引数です。
基本的な動作の違い
-
recursive = FALSE(デフォルト)- 指定したパス(フォルダ)の直下にあるファイルやフォルダのみをリストアップします。サブフォルダの中身までは見に行きません。
-
recursive = TRUE- 指定したパスの中にあるサブフォルダ、さらにその中のサブフォルダ…と、階層を一番下まで掘り下げてすべてのファイルを探し出します。
具体例
以下のようなフォルダ構造が手元にあるとします。
my_folder/
├── file_A.txt
└── sub_folder/
├── file_B.txt
└── file_C.csvこの my_folder に対して dir を実行した場合の違いは以下のようになります。
recursive = FALSE の場合(デフォルト)
dir(path = "my_folder", recursive = FALSE)出力:
[1] "file_A.txt" "sub_folder"直下にあるファイル名と、サブフォルダの「名前」だけが返ってきます。
recursive = TRUE の場合
dir(path = "my_folder", recursive = TRUE)出力:
[1] "file_A.txt" "sub_folder/file_B.txt" "sub_folder/file_C.csv"サブフォルダの中身まで検索され、「サブフォルダ名/ファイル名」という形でリストアップされます。
なお、デフォルト設定(include.dirs = FALSE)では、空のフォルダそのものはリストに表示されず、ファイルのみが抽出されます。
パターン指定(特定の拡張子だけを探す)
プロジェクトフォルダ内の「すべての階層」から、.csv ファイルだけを抽出したい場合。
dir(path = ".", pattern = "\\.csv$", recursive = TRUE)フルパスの取得
recursive = TRUE で見つけたファイルを read.csv() などで読み込みたい場合、full.names = TRUE を一緒に指定した方が確実です。
指定しませんと、作業ディレクトリ(カレントディレクトリ)からの正しいパスが取得できず、エラーになることがあります。
# 完全なファイルパスとして取得する
csv_files <- dir(path = "my_folder", pattern = "\\.csv$",
recursive = TRUE, full.names = TRUE)
# 上記指定で lapply 等を使って一括読み込みができるようになります
# data_list <- lapply(csv_files, read.csv)関数 file.copy
Rの file.copy 関数における recursive 引数について確認します。
関数 dir では「フォルダの中身を階層の底まで探すかどうか」でしたが、file.copy における recursive は「フォルダ(ディレクトリ)ごと、その中身を丸ごとコピーするかどうか」を指定します。
基本的な動作の違い
-
recursive = FALSE(デフォルト)- 「ファイル」しかコピーできません。
- もし
from(コピー元)にフォルダを指定した場合、ソースコードの以下の部分が働き、「フォルダはスキップされました」という警告(warning)が出てコピーされません。
warning("directories are omitted unless 'recursive = TRUE'")-
recursive = TRUE- 指定した「フォルダそのもの」と「その中に含まれるすべてのファイル・サブフォルダ」を丸ごとコピーします。
コピー先(to)は「既に存在する1つのフォルダ」である必要があります
以下は関数コードからの抜粋です。
else if (recursive)
warning("'recursive' will be ignored as 'to' is not a single existing directory")recursive = TRUE を使ってフォルダごとコピーする場合、コピー先(to)はすでに作成されているフォルダ(ディレクトリ)を指定する必要があります。
存在しないフォルダ名や、複数の場所を指定すると、recursive は無視されてしまいます。(事前に 関数 dir.create 等でコピー先フォルダを作っておく必要があります)
overwrite(上書き)のデフォルト設定が変わります
以下は関数の引数定義です。
function (from, to, overwrite = recursive, recursive = FALSE, ...)通常、file.copy は安全のため上書き保存しませんが、recursive = TRUE にすると、連動して overwrite = TRUE になります。
つまり、フォルダごとコピーした際、コピー先に同名のファイルがあった場合は問答無用で上書きされます。
上書きしたくない場合は、明示的に overwrite = FALSE を指定する必要があります。
自分自身の中へのコピー(無限ループ)の防止
以下は関数コードからの抜粋です。
if (recursive && to %in% from)
stop("attempt to copy a directory to itself")フォルダを、そのフォルダ自身の中にコピーしようとすると無限ループになるため、エラー(stop)になるよう安全対策がされています。
具体例
以下のような状況を想定します。
- コピー元:
project_Aというフォルダ(中に複数のファイルやサブフォルダがある) - コピー先:
backupというフォルダ(既に作成済みとする)
失敗例(recursive = FALSE のまま)
file.copy(from = "project_A", to = "backup")結果:
FALSE が返り、「directories are omitted unless ‘recursive = TRUE’」という警告が出ます。中身は何もコピーされません。
成功例(recursive = TRUE を指定)
file.copy(from = "project_A", to = "backup", recursive = TRUE)結果:
backup フォルダの中に、project_A というフォルダが丸ごと(中身のファイル・サブフォルダごと)コピーされます。 (パスで言うと backup/project_A/元のファイルたち... という状態になります)
以上です。

