C# サンプル集 |
Visual Basic 中学校 > C# サンプル集 > C# サンプル集目次 >
ファイルを複数コピーする
2020/7/19
フォルダー内のファイルをすべてコピーする
string folderFrom =
@"C:\FileTest\FolderA";
//コピー元のフォルダー string folderTo = @"C:\FileTest\FolderB"; //コピー先のフォルダー //foreach (string pathFrom in System.IO.Directory.GetFiles(folderFrom)) //←.NET Framework 3.5以前の場合 foreach (string pathFrom in System.IO.Directory.EnumerateFiles(folderFrom)) { //コピー先のパスを作成 string pathTo = pathFrom.Replace(folderFrom, folderTo); //コピー先のフォルダーが存在するか確認し、なければ作成します。 string targetFolder = System.IO.Path.GetDirectoryName(pathTo); if (System.IO.Directory.Exists(targetFolder) == false) { System.IO.Directory.CreateDirectory(targetFolder); } //1ファイルのコピー実行。同名のファイルがある場合上書きします。 System.Diagnostics.Debug.WriteLine("コピー" + pathFrom + " → " + pathTo); System.IO.File.Copy(pathFrom, pathTo, true); //こちらでコピーするとコピー先に同名のファイルがあると上書きせずエラーになります。 //System.IO.File.Copy(pathFrom, pathTo); } |
- コピー先のファイルが既に存在する場合、上書きします。
- コピー先のフォルダーが存在しない場合、フォルダーを作成します。
- サブフォルダー(子フォルダー)は対象外です。
フォルダー内のファイルをサブフォルダーも含んですべてコピーする
この例は、サブフォルダー(子フォルダー)内にあるファイルもすべて対象にします。
string folderFrom =
@"C:\FileTest\FolderA";
//コピー元のフォルダー string folderTo = @"C:\FileTest\FolderB"; //コピー先のフォルダー //foreach (string pathFrom in System.IO.Directory.GetFiles(folderFrom, "*", System.IO.SearchOption.AllDirectories)) //←.NET Framework 3.5以前の場合 foreach (string pathFrom in System.IO.Directory.EnumerateFiles(folderFrom, "*", System.IO.SearchOption.AllDirectories)) { //コピー先のパスを作成 string pathTo = pathFrom.Replace(folderFrom, folderTo); //コピー先のフォルダーが存在するか確認し、なければ作成します。 string targetFolder = System.IO.Path.GetDirectoryName(pathTo); if (System.IO.Directory.Exists(targetFolder) == false) { System.IO.Directory.CreateDirectory(targetFolder); } //1ファイルのコピー実行。同名のファイルがある場合上書きします。 System.Diagnostics.Debug.WriteLine("コピー" + pathFrom + " → " + pathTo); System.IO.File.Copy(pathFrom, pathTo, true); //こちらでコピーするとコピー先に同名のファイルがあると上書きせずエラーになります。 //System.IO.File.Copy(pathFrom, pathTo); } |
- コピー先のファイルが既に存在する場合、上書きします。
- コピー先のフォルダーが存在しない場合、フォルダーを作成します。
- シンボリックリンクなどで上位のフォルダーがリンクされている場合など、この処理は無限ループになります。
フォルダー内の拡張子が csv のファイルをすべてコピーする
GetFilesメソッドの第2引数で、対象のファイルを選択するワイルドカードを指定できます。この例では *.csv を指定して csv ファイルだけを対象にしています。
string folderFrom =
@"C:\FileTest\FolderA";
//コピー元のフォルダー string folderTo = @"C:\FileTest\FolderB"; //コピー先のフォルダー //foreach (string pathFrom in System.IO.Directory.GetFiles(folderFrom, "*.csv")) //←.NET Framework 3.5以前の場合 foreach (string pathFrom in System.IO.Directory.EnumerateFiles(folderFrom, "*.csv")) { //コピー先のパスを作成 string pathTo = pathFrom.Replace(folderFrom, folderTo); //コピー先のフォルダーが存在するか確認し、なければ作成します。 string targetFolder = System.IO.Path.GetDirectoryName(pathTo); if (System.IO.Directory.Exists(targetFolder) == false) { System.IO.Directory.CreateDirectory(targetFolder); } //1ファイルのコピー実行。同名のファイルがある場合上書きします。 System.Diagnostics.Debug.WriteLine("コピー" + pathFrom + " → " + pathTo); System.IO.File.Copy(pathFrom, pathTo, true); //こちらでコピーするとコピー先に同名のファイルがあると上書きせずエラーになります。 //System.IO.File.Copy(pathFrom, pathTo); } |
- コピー先のファイルが既に存在する場合、上書きします。
- コピー先のフォルダーが存在しない場合、フォルダーを作成します。
- サブフォルダー(子フォルダー)は対象外です。
フォルダー内の拡張子が csv のファイルをサブフォルダーも含んですべてコピーする
この例は、サブフォルダー(子フォルダー)内にあるファイルもすべて対象にします。
string folderFrom =
@"C:\FileTest\FolderA";
//コピー元のフォルダー string folderTo = @"C:\FileTest\FolderB"; //コピー先のフォルダー //foreach (string pathFrom in System.IO.Directory.GetFiles(folderFrom, "*.csv", System.IO.SearchOption.AllDirectories)) //←.NET Framework 3.5以前の場合 foreach (string pathFrom in System.IO.Directory.EnumerateFiles(folderFrom, "*.csv", System.IO.SearchOption.AllDirectories)) { //コピー先のパスを作成 string pathTo = pathFrom.Replace(folderFrom, folderTo); //コピー先のフォルダーが存在するか確認し、なければ作成します。 string targetFolder = System.IO.Path.GetDirectoryName(pathTo); if (System.IO.Directory.Exists(targetFolder) == false) { System.IO.Directory.CreateDirectory(targetFolder); } //1ファイルのコピー実行。同名のファイルがある場合上書きします。 System.Diagnostics.Debug.WriteLine("コピー" + pathFrom + " → " + pathTo); System.IO.File.Copy(pathFrom, pathTo, true); //こちらでコピーするとコピー先に同名のファイルがあると上書きせずエラーになります。 //System.IO.File.Copy(pathFrom, pathTo); } |
- コピー先のファイルが既に存在する場合、上書きします。
- コピー先のフォルダーが存在しない場合、フォルダーを作成します。
- シンボリックリンクなどで上位のフォルダーがリンクされている場合など、この処理は無限ループになります。
フォルダー内の拡張子が csv のファイルをダイアログを表示してコピーする
何事もなくすぐにコピーが終わる場合はダイアログが表示されません。
この例を実行するにはファイルの先頭の方に using System.Runtime.InteropServices; が必要です。
public void CopyTest() { var sf = new NativeMethods.SHFILEOPSTRUCT(); sf.wFunc = NativeMethods.FileFuncFlags.FO_COPY; //コピーを指示します。 sf.pFrom = @"C:\FileTest\FolderA\*.csv" + "\0"; sf.pTo = @"C:\FileTest\FolderB\" + "\0"; int result; result = NativeMethods.SHFileOperation(ref sf); if (result == 0) { System.Diagnostics.Debug.WriteLine("成功"); } else { System.Diagnostics.Debug.WriteLine("失敗。" + result); } } public class NativeMethods { /// <summary> /// ファイルをコピー・移動・削除・名前変更します。 /// </summary> /// <param name="lpFileOp"></param> /// <returns>正常時0。異常時の値の意味は https://docs.microsoft.com/ja-jp/windows/win32/api/shellapi/nf-shellapi-shfileoperationa を参照。</returns> [DllImport("shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern int SHFileOperation([In] ref SHFILEOPSTRUCT lpFileOp); [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct SHFILEOPSTRUCT { public IntPtr hwnd; [MarshalAs(UnmanagedType.U4)] public FileFuncFlags wFunc; [MarshalAs(UnmanagedType.LPWStr)] public string pFrom; [MarshalAs(UnmanagedType.LPWStr)] public string pTo; [MarshalAs(UnmanagedType.U2)] public FILEOP_FLAGS fFlags; [MarshalAs(UnmanagedType.Bool)] public bool ffAnyOperationsAborted; public IntPtr hNameMappings; //FOF_WANTMAPPINGHANDLEフラグとともに使用します。 [MarshalAs(UnmanagedType.LPWStr)] public string lplpszProgressTitle; //FOF_SIMPLEPROGRESSフラグとともに使用します。 } public enum FileFuncFlags { /// <summary>pFrom から pTo にファイルを移動します。</summary> FO_MOVE = 0x1, /// <summary>pFrom から pTo にファイルをコピーします。</summary> FO_COPY = 0x2, /// <summary>pFrom からファイルを削除します。</summary> FO_DELETE = 0x3, /// <summary>pFrom のファイルの名前を変更します。複数ファイルを対象とする場合は FO_MOVE を使用します。</summary> FO_RENAME = 0x4 } [Flags] public enum FILEOP_FLAGS : short { /// <summary>pToにはpFromに1対1で対応する複数のコピー先を指定します。</summary> FOF_MULTIDESTFILES = 0x1, /// <summary>このフラグは使用しません。</summary> FOF_CONFIRMMOUSE = 0x2, /// <summary>進捗状況のダイアログを表示しません。</summary> FOF_SILENT = 0x4, /// <summary>同名のファイルが既に存在する場合、新しい名前を付けます。</summary> FOF_RENAMEONCOLLISION = 0x8, /// <summary>確認ダイアログを表示せず、すべて「はい」を選択したものとします。</summary> FOF_NOCONFIRMATION = 0x10, /// <summary>FOF_RENAMEONCOLLISIONフラグによるファイル名の衝突回避が発生した場合、SHFILEOPSTRUCT.hNameMappingsに新旧ファイル名の情報を格納します。この情報はSHFreeNameMappingsを使って開放する必要があります。</summary> FOF_WANTMAPPINGHANDLE = 0x20, /// <summary>可能であれば、操作を元に戻せるようにします。</summary> FOF_ALLOWUNDO = 0x40, /// <summary>ワイルドカードが使用された場合、ファイルのみを対象とします。</summary> FOF_FILESONLY = 0x80, /// <summary>進捗状況のダイアログを表示しますが、個々のファイル名は表示しません。</summary> FOF_SIMPLEPROGRESS = 0x100, /// <summary>新しいフォルダーの作成する前にユーザーに確認しません。</summary> FOF_NOCONFIRMMKDIR = 0x200, /// <summary>エラーが発生してもダイアログを表示しません。</summary> FOF_NOERRORUI = 0x400, /// <summary>ファイルのセキュリティ属性はコピーしません。コピー後のファイルはコピー先のフォルダーのセキュリティ属性を引き継ぎます。</summary> FOF_NOCOPYSECURITYATTRIBS = 0x800, /// <summary>サブディレクトリーを再帰的に処理しません。これは既定の動作です。</summary> FOF_NORECURSION = 0x1000, /// <summary>グループとして連結しているファイルは移動しません。指定されたファイルだけを移動します。</summary> FOF_NO_CONNECTED_ELEMENTS = 0x2000, /// <summary>ファイルが恒久的に削除される場合、警告を表示します。このフラグはFOF_NOCONFIRMATIONより優先されます。 </summary> FOF_WANTNUKEWARNING = 0x4000, /// <summary>UIを表示しません。</summary> FOF_NO_UI = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR } } |
- コピーに時間がかかる場合、進捗状況のダイアログを表示します。
- コピー先のファイルが既に存在する場合、どのように処理するかユーザーに確認します。
- Windowsでのみ実行できます。(.NET Framework , .NET Core, .Net 5以降すべてで実行できます。)
- 何かエラーが発生した場合、エラーを表示します。
- このサンプルで使用している NativeMethods クラスは他のサンプルで使用しているものと完全に同じです。
この例の引数を変更して、「元に戻す」を可能にしたり、同名のファイルが存在する場合ファイル名を変更するなど動作をカスタマイズできます。ファイルを1つコピーする でいくつかサンプルを紹介します。
フォルダー内の拡張子が csv のファイルをサブフォルダーも含んでダイアログを表示してコピーする
SHFileOperationを擬似的に再帰的に(Recursive)実行することで、サブフォルダーも含んだ処理で進捗ダイアログを表示します。
何事もなくすぐにコピーが終わる場合はダイアログが表示されません。
この例を実行するにはファイルの先頭の方に using System.Runtime.InteropServices; が必要です。
public void CopyTest() { string folderFrom = @"C:\FileTest\FolderA"; //コピー元のフォルダー string folderTo = @"C:\FileTest\FolderB"; //コピー先のフォルダー string filePattern = "*.csv"; var sf = new NativeMethods.SHFILEOPSTRUCT(); sf.wFunc = NativeMethods.FileFuncFlags.FO_COPY; //コピーを指示します。 sf.fFlags = NativeMethods.FILEOP_FLAGS.FOF_MULTIDESTFILES; sf.fFlags = sf.fFlags | NativeMethods.FILEOP_FLAGS.FOF_NOCONFIRMATION; //上書き確認ダイアログを表示せず、上書きします。 sf.fFlags = sf.fFlags | NativeMethods.FILEOP_FLAGS.FOF_NOCONFIRMMKDIR; //フォルダー作成の確認ダイアログを表示せずフォルダーを作成します。 sf.fFlags = sf.fFlags | NativeMethods.FILEOP_FLAGS.FOF_NOERRORUI; //エラーダイアログを表示しません。 var foldersFrom = new System.Collections.Generic.List<string>(); var foldersTo = new System.Collections.Generic.List<string>(); foldersFrom.Add(folderFrom + "\\" + filePattern); foldersTo.Add(folderTo + "\\"); foreach (string fileName in System.IO.Directory.GetFiles(folderFrom, filePattern , System.IO.SearchOption.AllDirectories)) { string folder = System.IO.Path.GetDirectoryName(fileName); if (foldersFrom.Contains(folder + "\\" + filePattern)) { continue; } foldersFrom.Add(folder + "\\" + filePattern); foldersTo.Add(folder.Replace(folderFrom, folderTo) + "\\"); } sf.pFrom = String.Join("\0", foldersFrom) + "\0"; sf.pTo = String.Join("\0", foldersTo) + "\0"; int result; result = NativeMethods.SHFileOperation(ref sf); if (result == 0) { System.Diagnostics.Debug.WriteLine("成功"); } else { System.Diagnostics.Debug.WriteLine("失敗。" + result); } } public class NativeMethods { /// <summary> /// ファイルをコピー・移動・削除・名前変更します。 /// </summary> /// <param name="lpFileOp"></param> /// <returns>正常時0。異常時の値の意味は https://docs.microsoft.com/ja-jp/windows/win32/api/shellapi/nf-shellapi-shfileoperationa を参照。</returns> [DllImport("shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern int SHFileOperation([In] ref SHFILEOPSTRUCT lpFileOp); [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct SHFILEOPSTRUCT { public IntPtr hwnd; [MarshalAs(UnmanagedType.U4)] public FileFuncFlags wFunc; [MarshalAs(UnmanagedType.LPWStr)] public string pFrom; [MarshalAs(UnmanagedType.LPWStr)] public string pTo; [MarshalAs(UnmanagedType.U2)] public FILEOP_FLAGS fFlags; [MarshalAs(UnmanagedType.Bool)] public bool ffAnyOperationsAborted; public IntPtr hNameMappings; //FOF_WANTMAPPINGHANDLEフラグとともに使用します。 [MarshalAs(UnmanagedType.LPWStr)] public string lplpszProgressTitle; //FOF_SIMPLEPROGRESSフラグとともに使用します。 } public enum FileFuncFlags { /// <summary>pFrom から pTo にファイルを移動します。</summary> FO_MOVE = 0x1, /// <summary>pFrom から pTo にファイルをコピーします。</summary> FO_COPY = 0x2, /// <summary>pFrom からファイルを削除します。</summary> FO_DELETE = 0x3, /// <summary>pFrom のファイルの名前を変更します。複数ファイルを対象とする場合は FO_MOVE を使用します。</summary> FO_RENAME = 0x4 } [Flags] public enum FILEOP_FLAGS : short { /// <summary>pToにはpFromに1対1で対応する複数のコピー先を指定します。</summary> FOF_MULTIDESTFILES = 0x1, /// <summary>このフラグは使用しません。</summary> FOF_CONFIRMMOUSE = 0x2, /// <summary>進捗状況のダイアログを表示しません。</summary> FOF_SILENT = 0x4, /// <summary>同名のファイルが既に存在する場合、新しい名前を付けます。</summary> FOF_RENAMEONCOLLISION = 0x8, /// <summary>確認ダイアログを表示せず、すべて「はい」を選択したものとします。</summary> FOF_NOCONFIRMATION = 0x10, /// <summary>FOF_RENAMEONCOLLISIONフラグによるファイル名の衝突回避が発生した場合、SHFILEOPSTRUCT.hNameMappingsに新旧ファイル名の情報を格納します。この情報はSHFreeNameMappingsを使って開放する必要があります。</summary> FOF_WANTMAPPINGHANDLE = 0x20, /// <summary>可能であれば、操作を元に戻せるようにします。</summary> FOF_ALLOWUNDO = 0x40, /// <summary>ワイルドカードが使用された場合、ファイルのみを対象とします。</summary> FOF_FILESONLY = 0x80, /// <summary>進捗状況のダイアログを表示しますが、個々のファイル名は表示しません。</summary> FOF_SIMPLEPROGRESS = 0x100, /// <summary>新しいフォルダーの作成する前にユーザーに確認しません。</summary> FOF_NOCONFIRMMKDIR = 0x200, /// <summary>エラーが発生してもダイアログを表示しません。</summary> FOF_NOERRORUI = 0x400, /// <summary>ファイルのセキュリティ属性はコピーしません。コピー後のファイルはコピー先のフォルダーのセキュリティ属性を引き継ぎます。</summary> FOF_NOCOPYSECURITYATTRIBS = 0x800, /// <summary>サブディレクトリーを再帰的に処理しません。これは既定の動作です。</summary> FOF_NORECURSION = 0x1000, /// <summary>グループとして連結しているファイルは移動しません。指定されたファイルだけを移動します。</summary> FOF_NO_CONNECTED_ELEMENTS = 0x2000, /// <summary>ファイルが恒久的に削除される場合、警告を表示します。このフラグはFOF_NOCONFIRMATIONより優先されます。 </summary> FOF_WANTNUKEWARNING = 0x4000, /// <summary>UIを表示しません。</summary> FOF_NO_UI = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR } } |
- コピー先のファイルが既に存在する場合、上書きします。
- コピー先のフォルダーが存在しない場合、フォルダーを作成します。
- シンボリックリンクなどで上位のフォルダーがリンクされている場合など、この処理は無限ループになります。
- Windowsでのみ実行できます。(.NET Framework , .NET Core, .Net 5以降すべてで実行できます。)
- このサンプルで使用している NativeMethods クラスは他のサンプルで使用しているものと完全に同じです。
この例の引数を変更して、「元に戻す」を可能にしたり、同名のファイルが存在する場合ファイル名を変更するなど動作をカスタマイズできます。ファイルを1つコピーする でいくつかサンプルを紹介します。