문제
내가 원하는 전체를 복사 디렉토리의 내용을 한 위치에서 다른 위치에 있습니다.
가 나타나지 않을 것을 할 수 있는 방법을 사용하여 이를 System.IO
클래스고 없이 많이 재귀.
는 방법이 있습니다 VB 는 우리가 사용할 수 있습니다면 우리는 참조를 추가 Microsoft.VisualBasic
:
new Microsoft.VisualBasic.Devices.Computer().
FileSystem.CopyDirectory( sourceFolder, outputFolder );
이처럼 보이는 오히려 추한 해킹하는 것입니다.은 더 나은 방법이 있을까?
해결책
훨씬 쉽
//Now Create all of the directories
foreach (string dirPath in Directory.GetDirectories(SourcePath, "*",
SearchOption.AllDirectories))
Directory.CreateDirectory(dirPath.Replace(SourcePath, DestinationPath));
//Copy all the files & Replaces any files with the same name
foreach (string newPath in Directory.GetFiles(SourcePath, "*.*",
SearchOption.AllDirectories))
File.Copy(newPath, newPath.Replace(SourcePath, DestinationPath), true);
다른 팁
Hmm,나는 생각한 오해하고 질문에 나만 위험하다.무엇을 잘못으로 다음과 같은 간단한 방법이 있나요?
public static void CopyFilesRecursively(DirectoryInfo source, DirectoryInfo target) {
foreach (DirectoryInfo dir in source.GetDirectories())
CopyFilesRecursively(dir, target.CreateSubdirectory(dir.Name));
foreach (FileInfo file in source.GetFiles())
file.CopyTo(Path.Combine(target.FullName, file.Name));
}
편집 이 게시물을 얻고있는 인상적인 수 downvotes 을 위한 이러한 간단한 대답을 동등하게 간단한 질문하자,나를 추가 설명입니다. 하십시오 이것을 읽기 전에 downvoting.
첫째, 이 코드는 intendend 로체 코드에서 질문입니다.그것은 그림에 대한 목적만 있습니다.
Microsoft.VisualBasic.Devices.Computer.FileSystem.CopyDirectory
는 몇 가지 추가 정확성 테스트(예:지 원본과 목표가 유효한 디렉토리지원이 부모의 대상 etc.) 에서 누락된 이 대답이다.는 코드는 아마도 더 많은 최적화되어 있습니다.
는 말했다,코드 잘 작동.그 가 (거의 동일하게)에서 사용되고 성숙한 소프트웨어에 대한 년이다.그 외에도에서 고유한 반복 존재하는 모든 입출력 처리(예:어떻게 될 경우에는 사용자가 수동으로 연결을 끊는 USB 드라이브는 동안 당신의 코드 작성을 그것은?), 이 없 알려진 문제를 해결합니다.
특히,지적하고 싶다는 것의 사용을 재귀 여기에 절대적으로 문제가 되지 않습니다.도 이론(을 개념적으로,그것의 가장 우아한 솔루션)도에서 실습한다: 이 코드는 것이지 오버플로우 스.스택을 충분히 큰 손잡이도 많이 중첩된 파일의 계층 구조입니다.오래 전에 스택에 공간이 문제가되면,폴더의 경로 길이 제한이 있습니다.
시 사용자는 악성 할 수 있는 이것을 가정하여 깊이 중첩된 디렉토리의 하나의 문자는 각.나는이 노력을하지 않았습니다.하지만 단지 설명:을 만들기 위해 이 코드는 오버플로우에는 전형적인 컴퓨터,디렉토리어야 할 것이 중첩된 몇 가지 천 다.이것은 단순히지 않는 현실적인 시나리오이다.
에서 복사 MSDN:
using System;
using System.IO;
class CopyDir
{
public static void Copy(string sourceDirectory, string targetDirectory)
{
DirectoryInfo diSource = new DirectoryInfo(sourceDirectory);
DirectoryInfo diTarget = new DirectoryInfo(targetDirectory);
CopyAll(diSource, diTarget);
}
public static void CopyAll(DirectoryInfo source, DirectoryInfo target)
{
Directory.CreateDirectory(target.FullName);
// Copy each file into the new directory.
foreach (FileInfo fi in source.GetFiles())
{
Console.WriteLine(@"Copying {0}\{1}", target.FullName, fi.Name);
fi.CopyTo(Path.Combine(target.FullName, fi.Name), true);
}
// Copy each subdirectory using recursion.
foreach (DirectoryInfo diSourceSubDir in source.GetDirectories())
{
DirectoryInfo nextTargetSubDir =
target.CreateSubdirectory(diSourceSubDir.Name);
CopyAll(diSourceSubDir, nextTargetSubDir);
}
}
public static void Main()
{
string sourceDirectory = @"c:\sourceDirectory";
string targetDirectory = @"c:\targetDirectory";
Copy(sourceDirectory, targetDirectory);
}
// Output will vary based on the contents of the source directory.
}
이것을 보십시오:
Process proc = new Process();
proc.StartInfo.UseShellExecute = true;
proc.StartInfo.FileName = Path.Combine(Environment.SystemDirectory, "xcopy.exe");
proc.StartInfo.Arguments = @"C:\source C:\destination /E /I";
proc.Start();
귀하의 xcopy 인수를 따라 다를 수 있지만 당신은 아이디어를 얻을 수 있습니다.
또는,당신이 원하는 어려운 길을 가야하는 참조를 추가 프로젝트를 위한 Microsoft.Visual basic 다음 사용하려면 다음을 사용합니다.
Microsoft.VisualBasic.FileIO.FileSystem.CopyDirectory(fromDirectory, toDirectory);
그러나 중 하나를 사용하여,재귀적 기능에 더 나은 방법이 가지 않을 것이기 때문을 로드하는 데 필요 VB dll.
이 사이트는 항상 나를 도왔을 많이,그리고 지금 그것은 내가 다른 사람들을 돕기 위해 무엇으로 나가 알고있다.
나는 나의 코드는 아래에 유용합니다.
string source_dir = @"E:\";
string destination_dir = @"C:\";
// substring is to remove destination_dir absolute path (E:\).
// Create subdirectory structure in destination
foreach (string dir in System.IO.Directory.GetDirectories(source_dir, "*", System.IO.SearchOption.AllDirectories))
{
System.IO.Directory.CreateDirectory(System.IO.Path.Combine(destination_dir, dir.Substring(source_dir.Length + 1)));
// Example:
// > C:\sources (and not C:\E:\sources)
}
foreach (string file_name in System.IO.Directory.GetFiles(source_dir, "*", System.IO.SearchOption.AllDirectories))
{
System.IO.File.Copy(file_name, System.IO.Path.Combine(destination_dir, file_name.Substring(source_dir.Length + 1)));
}
폴더 복사지 않고 재귀적으로 재귀를 방지하 stack overflow.
public static void CopyDirectory(string source, string target)
{
var stack = new Stack<Folders>();
stack.Push(new Folders(source, target));
while (stack.Count > 0)
{
var folders = stack.Pop();
Directory.CreateDirectory(folders.Target);
foreach (var file in Directory.GetFiles(folders.Source, "*.*"))
{
File.Copy(file, Path.Combine(folders.Target, Path.GetFileName(file)));
}
foreach (var folder in Directory.GetDirectories(folders.Source))
{
stack.Push(new Folders(folder, Path.Combine(folders.Target, Path.GetFileName(folder))));
}
}
}
public class Folders
{
public string Source { get; private set; }
public string Target { get; private set; }
public Folders(string source, string target)
{
Source = source;
Target = target;
}
}
여기에는 유틸성 클래스를 사용했던 IO 작업은 이렇습니다.
using System;
using System.Runtime.InteropServices;
namespace MyNameSpace
{
public class ShellFileOperation
{
private static String StringArrayToMultiString(String[] stringArray)
{
String multiString = "";
if (stringArray == null)
return "";
for (int i=0 ; i<stringArray.Length ; i++)
multiString += stringArray[i] + '\0';
multiString += '\0';
return multiString;
}
public static bool Copy(string source, string dest)
{
return Copy(new String[] { source }, new String[] { dest });
}
public static bool Copy(String[] source, String[] dest)
{
Win32.SHFILEOPSTRUCT FileOpStruct = new Win32.SHFILEOPSTRUCT();
FileOpStruct.hwnd = IntPtr.Zero;
FileOpStruct.wFunc = (uint)Win32.FO_COPY;
String multiSource = StringArrayToMultiString(source);
String multiDest = StringArrayToMultiString(dest);
FileOpStruct.pFrom = Marshal.StringToHGlobalUni(multiSource);
FileOpStruct.pTo = Marshal.StringToHGlobalUni(multiDest);
FileOpStruct.fFlags = (ushort)Win32.ShellFileOperationFlags.FOF_NOCONFIRMATION;
FileOpStruct.lpszProgressTitle = "";
FileOpStruct.fAnyOperationsAborted = 0;
FileOpStruct.hNameMappings = IntPtr.Zero;
int retval = Win32.SHFileOperation(ref FileOpStruct);
if(retval != 0) return false;
return true;
}
public static bool Move(string source, string dest)
{
return Move(new String[] { source }, new String[] { dest });
}
public static bool Delete(string file)
{
Win32.SHFILEOPSTRUCT FileOpStruct = new Win32.SHFILEOPSTRUCT();
FileOpStruct.hwnd = IntPtr.Zero;
FileOpStruct.wFunc = (uint)Win32.FO_DELETE;
String multiSource = StringArrayToMultiString(new string[] { file });
FileOpStruct.pFrom = Marshal.StringToHGlobalUni(multiSource);
FileOpStruct.pTo = IntPtr.Zero;
FileOpStruct.fFlags = (ushort)Win32.ShellFileOperationFlags.FOF_SILENT | (ushort)Win32.ShellFileOperationFlags.FOF_NOCONFIRMATION | (ushort)Win32.ShellFileOperationFlags.FOF_NOERRORUI | (ushort)Win32.ShellFileOperationFlags.FOF_NOCONFIRMMKDIR;
FileOpStruct.lpszProgressTitle = "";
FileOpStruct.fAnyOperationsAborted = 0;
FileOpStruct.hNameMappings = IntPtr.Zero;
int retval = Win32.SHFileOperation(ref FileOpStruct);
if(retval != 0) return false;
return true;
}
public static bool Move(String[] source, String[] dest)
{
Win32.SHFILEOPSTRUCT FileOpStruct = new Win32.SHFILEOPSTRUCT();
FileOpStruct.hwnd = IntPtr.Zero;
FileOpStruct.wFunc = (uint)Win32.FO_MOVE;
String multiSource = StringArrayToMultiString(source);
String multiDest = StringArrayToMultiString(dest);
FileOpStruct.pFrom = Marshal.StringToHGlobalUni(multiSource);
FileOpStruct.pTo = Marshal.StringToHGlobalUni(multiDest);
FileOpStruct.fFlags = (ushort)Win32.ShellFileOperationFlags.FOF_NOCONFIRMATION;
FileOpStruct.lpszProgressTitle = "";
FileOpStruct.fAnyOperationsAborted = 0;
FileOpStruct.hNameMappings = IntPtr.Zero;
int retval = Win32.SHFileOperation(ref FileOpStruct);
if(retval != 0) return false;
return true;
}
}
}
미성년자에 대한 개선 d4nt 의 대답은,아마 당신이 원하는 오류를 확인하고 변경하지 않 xcopy 경로에서 작업할 경우 서버 및 개발하기:
public void CopyFolder(string source, string destination)
{
string xcopyPath = Environment.GetEnvironmentVariable("WINDIR") + @"\System32\xcopy.exe";
ProcessStartInfo info = new ProcessStartInfo(xcopyPath);
info.UseShellExecute = false;
info.RedirectStandardOutput = true;
info.Arguments = string.Format("\"{0}\" \"{1}\" /E /I", source, destination);
Process process = Process.Start(info);
process.WaitForExit();
string result = process.StandardOutput.ReadToEnd();
if (process.ExitCode != 0)
{
// Or your own custom exception, or just return false if you prefer.
throw new InvalidOperationException(string.Format("Failed to copy {0} to {1}: {2}", source, destination, result));
}
}
만약 당신이 좋아하는 콘라드의 인기있는 대답을,하지만 당신이 원 source
자체는 아래의 폴더 target
, 보다는 오히려,그것의 어린이는 target
폴더,여기에는 코드입니다.그것을 반환합니다 새로 만든 DirectoryInfo
, 편리:
public static DirectoryInfo CopyFilesRecursively(DirectoryInfo source, DirectoryInfo target)
{
var newDirectoryInfo = target.CreateSubdirectory(source.Name);
foreach (var fileInfo in source.GetFiles())
fileInfo.CopyTo(Path.Combine(newDirectoryInfo.FullName, fileInfo.Name));
foreach (var childDirectoryInfo in source.GetDirectories())
CopyFilesRecursively(childDirectoryInfo, newDirectoryInfo);
return newDirectoryInfo;
}
당신은 항상 사용할 수 있습니다 이, 촬영에서 마이크로 소프트의 웹 사이트입니다.
static void Main()
{
// Copy from the current directory, include subdirectories.
DirectoryCopy(".", @".\temp", true);
}
private static void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs)
{
// Get the subdirectories for the specified directory.
DirectoryInfo dir = new DirectoryInfo(sourceDirName);
if (!dir.Exists)
{
throw new DirectoryNotFoundException(
"Source directory does not exist or could not be found: "
+ sourceDirName);
}
DirectoryInfo[] dirs = dir.GetDirectories();
// If the destination directory doesn't exist, create it.
if (!Directory.Exists(destDirName))
{
Directory.CreateDirectory(destDirName);
}
// Get the files in the directory and copy them to the new location.
FileInfo[] files = dir.GetFiles();
foreach (FileInfo file in files)
{
string temppath = Path.Combine(destDirName, file.Name);
file.CopyTo(temppath, false);
}
// If copying subdirectories, copy them and their contents to new location.
if (copySubDirs)
{
foreach (DirectoryInfo subdir in dirs)
{
string temppath = Path.Combine(destDirName, subdir.Name);
DirectoryCopy(subdir.FullName, temppath, copySubDirs);
}
}
}
tboswell's 체 증거 버전(는 탄력있을 반복 패턴에 filepath)
public static void copyAll(string SourcePath , string DestinationPath )
{
//Now Create all of the directories
foreach (string dirPath in Directory.GetDirectories(SourcePath, "*", SearchOption.AllDirectories))
Directory.CreateDirectory(Path.Combine(DestinationPath ,dirPath.Remove(0, SourcePath.Length )) );
//Copy all the files & Replaces any files with the same name
foreach (string newPath in Directory.GetFiles(SourcePath, "*.*", SearchOption.AllDirectories))
File.Copy(newPath, Path.Combine(DestinationPath , newPath.Remove(0, SourcePath.Length)) , true);
}
나의 솔루션은 기본적으로 수정@Termininja 의 대답은,그러나 나는 그것을 강화 조금 나보다 5 배 이상 빠른 속도를 받아 대답이다.
public static void CopyEntireDirectory(string path, string newPath)
{
Parallel.ForEach(Directory.GetFileSystemEntries(path, "*", SearchOption.AllDirectories)
,(fileName) =>
{
string output = Regex.Replace(fileName, "^" + Regex.Escape(path), newPath);
if (File.Exists(fileName))
{
Directory.CreateDirectory(Path.GetDirectoryName(output));
File.Copy(fileName, output, true);
}
else
Directory.CreateDirectory(output);
});
}
편집:수정@Ahmed Sabry 전체 병렬 foreach 생산지 않는 더 나은 결과는,그러나 코드를 사용하여 재귀적 기능과 그 이상적이지에서 일부는 상황이다.
public static void CopyEntireDirectory(DirectoryInfo source, DirectoryInfo target, bool overwiteFiles = true)
{
if (!source.Exists) return;
if (!target.Exists) target.Create();
Parallel.ForEach(source.GetDirectories(), (sourceChildDirectory) =>
CopyEntireDirectory(sourceChildDirectory, new DirectoryInfo(Path.Combine(target.FullName, sourceChildDirectory.Name))));
Parallel.ForEach(source.GetFiles(), sourceFile =>
sourceFile.CopyTo(Path.Combine(target.FullName, sourceFile.Name), overwiteFiles));
}
죄송 코드,그것은 여전히 버그:((먹이가 떨어진 가장 빠른 총 문제).여기에서 그것은 테스트를 작동합니다.키 SearchOption.AllDirectories,에 대한 필요성을 제거하는 명시적 재귀.
string path = "C:\\a";
string[] dirs = Directory.GetDirectories(path, "*.*", SearchOption.AllDirectories);
string newpath = "C:\\x";
try
{
Directory.CreateDirectory(newpath);
}
catch (IOException ex)
{
Console.WriteLine(ex.Message);
}
for (int j = 0; j < dirs.Length; j++)
{
try
{
Directory.CreateDirectory(dirs[j].Replace(path, newpath));
}
catch (IOException ex)
{
Console.WriteLine(ex.Message);
}
}
string[] files = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories);
for (int j = 0; j < files.Length; j++)
{
try
{
File.Copy(files[j], files[j].Replace(path, newpath));
}
catch (IOException ex)
{
Console.WriteLine(ex.Message);
}
}
이 코드는 희망이 도움말
private void KCOPY(string source, string destination)
{
if (IsFile(source))
{
string target = Path.Combine(destination, Path.GetFileName(source));
File.Copy(source, target, true);
}
else
{
string fileName = Path.GetFileName(source);
string target = System.IO.Path.Combine(destination, fileName);
if (!System.IO.Directory.Exists(target))
{
System.IO.Directory.CreateDirectory(target);
}
List<string> files = GetAllFileAndFolder(source);
foreach (string file in files)
{
KCOPY(file, target);
}
}
}
private List<string> GetAllFileAndFolder(string path)
{
List<string> allFile = new List<string>();
foreach (string dir in Directory.GetDirectories(path))
{
allFile.Add(dir);
}
foreach (string file in Directory.GetFiles(path))
{
allFile.Add(file);
}
return allFile;
}
private bool IsFile(string path)
{
if ((File.GetAttributes(path) & FileAttributes.Directory) == FileAttributes.Directory)
{
return false;
}
return true;
}
여기에는 확장을 위한 방법 또는 파일 이름이 시 a la FileInfo.CopyTo (참고 overwrite
매개 변수):
public static DirectoryInfo CopyTo(this DirectoryInfo sourceDir, string destinationPath, bool overwrite = false)
{
var sourcePath = sourceDir.FullName;
var destination = new DirectoryInfo(destinationPath);
destination.Create();
foreach (var sourceSubDirPath in Directory.EnumerateDirectories(sourcePath, "*", SearchOption.AllDirectories))
Directory.CreateDirectory(sourceSubDirPath.Replace(sourcePath, destinationPath));
foreach (var file in Directory.EnumerateFiles(sourcePath, "*", SearchOption.AllDirectories))
File.Copy(file, file.Replace(sourcePath, destinationPath), overwrite);
return destination;
}
그것은 되지 않을 수 있습니다 성능이 알고 있지만,나는 그것을 사용하 30MB 폴더와 그것을 완벽하게 작동합니다.Plus,내가 좋아하지 않은 모든 코드의 양과 재귀에 필요한 같은 쉬운 일이 아니다.
var source_folder = "c:\src";
var dest_folder = "c:\dest";
var zipFile = source_folder + ".zip";
ZipFile.CreateFromDirectory(source_folder, zipFile);
ZipFile.ExtractToDirectory(zipFile, dest_folder);
File.Delete(zipFile);
참고:Zip 파일이 사용할 수 있다.NET4.5+에서 시스템입니다.IO.압축 네임스페이스
보다 더 나은 어떤 코드(확장하는 방법 또는 파일 이름이 시과 재귀)
public static bool CopyTo(this DirectoryInfo source, string destination)
{
try
{
foreach (string dirPath in Directory.GetDirectories(source.FullName))
{
var newDirPath = dirPath.Replace(source.FullName, destination);
Directory.CreateDirectory(newDirPath);
new DirectoryInfo(dirPath).CopyTo(newDirPath);
}
//Copy all the files & Replaces any files with the same name
foreach (string filePath in Directory.GetFiles(source.FullName))
{
File.Copy(filePath, filePath.Replace(source.FullName,destination), true);
}
return true;
}
catch (IOException exp)
{
return false;
}
}
이용 클래스입니다.
public static class Extensions
{
public static void CopyTo(this DirectoryInfo source, DirectoryInfo target, bool overwiteFiles = true)
{
if (!source.Exists) return;
if (!target.Exists) target.Create();
Parallel.ForEach(source.GetDirectories(), (sourceChildDirectory) =>
CopyTo(sourceChildDirectory, new DirectoryInfo(Path.Combine(target.FullName, sourceChildDirectory.Name))));
foreach (var sourceFile in source.GetFiles())
sourceFile.CopyTo(Path.Combine(target.FullName, sourceFile.Name), overwiteFiles);
}
public static void CopyTo(this DirectoryInfo source, string target, bool overwiteFiles = true)
{
CopyTo(source, new DirectoryInfo(target), overwiteFiles);
}
}
한 변형만 하나 루프를 복사하의 모든 폴더와 파일을:
foreach (var f in Directory.GetFileSystemEntries(path, "*", SearchOption.AllDirectories))
{
var output = Regex.Replace(f, @"^" + path, newPath);
if (File.Exists(f)) File.Copy(f, output, true);
else Directory.CreateDirectory(output);
}
아래 코드는 microsoft 제안 을 복사 디렉토리
private static void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs = true)
{
// Get the subdirectories for the specified directory.
DirectoryInfo dir = new DirectoryInfo(sourceDirName);
if (!dir.Exists)
{
throw new DirectoryNotFoundException(
"Source directory does not exist or could not be found: "
+ sourceDirName);
}
DirectoryInfo[] dirs = dir.GetDirectories();
// If the destination directory doesn't exist, create it.
if (!Directory.Exists(destDirName))
{
Directory.CreateDirectory(destDirName);
}
// Get the files in the directory and copy them to the new location.
FileInfo[] files = dir.GetFiles();
foreach (FileInfo file in files)
{
string temppath = Path.Combine(destDirName, file.Name);
file.CopyTo(temppath, false);
}
// If copying subdirectories, copy them and their contents to new location.
if (copySubDirs)
{
foreach (DirectoryInfo subdir in dirs)
{
string temppath = Path.Combine(destDirName, subdir.Name);
DirectoryCopy(subdir.FullName, temppath, copySubDirs);
}
}
}
복사하려는 경우 콘텐츠 의 원 폴더와 하위 폴더 재귀적으로 당신은 단순히 사용하는 이를 다음과 같이 설명합니다:
string source = @"J:\source\";
string dest= @"J:\destination\";
DirectoryCopy(source, dest);
하지만 복사하려는 경우 원본 그 자체 디렉토리 (유사한 것을 마우스 오른쪽 단추로 클릭한 원본 폴더를 클릭한 복사본에서 다음 목적지 폴더를 클릭하여 붙여 넣)사용해야 합니다 다음과 같다:
string source = @"J:\source\";
string dest= @"J:\destination\";
DirectoryCopy(source, Path.Combine(dest, new DirectoryInfo(source).Name));
사본을 바꾸는 모든 파일 폴더의
public static void CopyAndReplaceAll(string SourcePath, string DestinationPath, string backupPath)
{
foreach (string dirPath in Directory.GetDirectories(SourcePath, "*", SearchOption.AllDirectories))
{
Directory.CreateDirectory($"{DestinationPath}{dirPath.Remove(0, SourcePath.Length)}");
Directory.CreateDirectory($"{backupPath}{dirPath.Remove(0, SourcePath.Length)}");
}
foreach (string newPath in Directory.GetFiles(SourcePath, "*.*", SearchOption.AllDirectories))
{
if (!File.Exists($"{ DestinationPath}{newPath.Remove(0, SourcePath.Length)}"))
File.Copy(newPath, $"{ DestinationPath}{newPath.Remove(0, SourcePath.Length)}");
else
File.Replace(newPath
, $"{ DestinationPath}{newPath.Remove(0, SourcePath.Length)}"
, $"{ backupPath}{newPath.Remove(0, SourcePath.Length)}", false);
}
}