FileSystemObjectのコピー移動削除の仕様調査結果

WSH(JScript)用ファイルライブラリ:FileUtility.jsを作成した時の調査結果です。

コピー/移動/削除

関数 同期/非同期 ドライブ間
fs.CopyFile 同期 可能
fs.CopyFolder 同期 可能
fs.MoveFile 同期 可能
fs.MoveFolder 同期 不可能
fs.DeleteFile 非同期 -
fs.DeleteFolder 非同期 -

FileSystemObjectは、fsとして記述します。

Existsの結果

Exists(fs.FileExists/fs.FolderExists)の結果は、ファイルが存在するタイミングでも、ファイルが存在しない結果(false)を返すことがある。
このため、Existsの挙動は、IF上のファイルの存在有無であり、内部処理上の存在有無ではない可能性がある。

上記の類推は、下記の挙動を確認したためである。

  1. ファイルを削除する(Deleteする)
  2. ファイルの存在を確認する(Existsする)
    • ファイルの削除を確認する(Existsの結果がfalseである)
  3. 削除したファイルと同名ファイルへリネームする(Moveする)
    • 「既に同名のファイルが存在しています。」エラーが発生する。
    • エラー発生頻度は、一定確率で発生する。そのため、大量に上記操作を繰り返すと、まれに発生する。
  4. エラーが発生した、リネーム(Move)を複数回繰り返す
    • 同一エラーを繰り返すが、最後には正常(エラーせず)にリネームが成功する。

fs.CopyFile/fs.CopyFolder(同期)

同期例:巨大ファイルをコピーする。
同期例:大量のファイルを含むフォルダをコピーする。

fs.MoveFile/fs.MoveFolder(同期)

同期例:巨大ファイルをドライブ間移動する。
MoveFolderは、MoveFileの動作から推察です。確証はありません。

fs.DeleteFile/fs.DeleteFolder(非同期)

非同期の確証となる挙動は、再現できませんでした。ただし、筆者の環境で大量に処理した場合、削除されていないと思われる動作をすることがまれに発生しました。

下記の掲示板の記載を発見したが、信憑性のほどは不明です。
掲示板過去の記事

いりや さん 2004年 02月 11日 19時 18分 18秒
// [1] ファイル削除が完了するまで待つ処理
// FileSystemObject>>deleteFile() メソッドは非同期に実行されることがわ
// かっている。つまりメソッドから返った時点ではファイルの削除が保証され

MoveFolder(ドライブ間フォルダ移動)

MoveFolder メソッド

重要 このメソッドを使用してボリューム間でフォルダを移動できるのは、オペレーティング システムでボリューム間のフォルダ移動がサポートされている場合だけです。

OSの環境依存のようです。筆者環境(Windows10)でMoveFolderは移動不可でした。CopyFolderとDeleteFolderで代用可能です。

MoveFileにも同様のメモがありますが、筆者環境(Windows10)でMoveFileは移動可能でした。

Windowsの最大パス長(260)

最大パス長のファイル/フォルダを処理する場合、エラー発生することがある。

最大パス長のファイル/フォルダを処理する場合、エラーが発生する場合がある。
fs.FileExists(), fs.FolderExists(), fs.GetAbsolutePathName()は、エラーしない。
fs.FileExists(), fs.FolderExists()は、ファイル/フォルダがある場合、falseを返す。
fs.GetFolder(fullpath).Files.Countは、エラーとなる可能背がある。
(以前エラーしたものがエラーしなくなている。100%発生ではない?)
new Enumerator(fs.GetFolder(fullpath).Files).atEnd()は、エラーとならない。
ただし、ファイルがある場合でも、trueを返す。
(パス長問題に該当しないファイルは、取得できる(atEnd()でtrueとならない))

問題環境作成方法(下記の操作をエクスプローラ上で行う)

./a/b            # フォルダを作成する
./a123456789/b   # 全体のパス長が260桁を超えるように、親フォルダの名称変更する
                 # 全体のパス長が260桁を超えるように、作成はできない
                 # 全体のパス長が260桁を超えるように、名称変更はできない

参考