निर्देशिका की पूरी सामग्री को C # में कॉपी करें


524

मैं निर्देशिका की पूरी सामग्री को एक स्थान से दूसरे स्थान पर C # में कॉपी करना चाहता हूं।

इसका उपयोग करने का एक तरीका प्रतीत नहीं होता है System.IOबहुत अधिक पुनरावृत्ति के बिना कक्षाओं ।

VB में एक विधि है जिसका उपयोग हम कर सकते हैं यदि हम एक संदर्भ जोड़ते हैं Microsoft.VisualBasic:

new Microsoft.VisualBasic.Devices.Computer().
    FileSystem.CopyDirectory( sourceFolder, outputFolder );

यह एक बदसूरत हैक की तरह लगता है। क्या कोई बेहतर तरीका है?


101
मैं कहूंगा कि नीचे पोस्ट किए गए विकल्पों को देखते हुए, कि वीबी तरीका इतना बदसूरत नहीं दिखता है।
केविन कर्शव

41
.NET फ्रेमवर्क का हिस्सा होने पर यह हैक कैसे हो सकता है? कोड लिखना बंद करें और आपको जो मिला है उसका उपयोग करें।
एमीसिको

15
यह एक सामान्य गलत धारणा है। Microsft.VisualBasic में सभी सामान्य विज़ुअल बेसिक प्रक्रियाएँ हैं जो VB में कोडिंग को इतना आसान बनाती हैं। Microsot.VisualBasic.Compatibility विधानसभा VB6 विरासत के लिए उपयोग किया जाता है।
एमीसिको

63
Microsoft.VisualBasic.Devices.Computer.FileSystem पर कोड की 2,000 से अधिक लाइनें हैं। CopyDirectory यह सुनिश्चित करती है कि आप पैरेंट फोल्डर को चाइल्ड फोल्डर और अन्य चेक में कॉपी नहीं कर रहे हैं। यह अत्यधिक अनुकूलित है, और इसी तरह। चयनित उत्तर सबसे अच्छा नाजुक कोड है।
एमीसिको

17
@AMissico - ठीक है, तो यह अनुकूलित और पूर्ण कोड में क्यों है Microsoft.VisualBasicऔर नहीं System.IO? इसका कारण मोनो में नहीं है क्योंकि सभी पुस्तकालय जिन्हें 'कोर' माना जाता है System.[something]- अन्य सभी नहीं हैं। मुझे अतिरिक्त DLL को संदर्भित करने में कोई समस्या नहीं है, लेकिन Microsoft द्वारा इस सुविधा को शामिल नहीं करने का एक अच्छा कारण है System.IO
कीथ

जवाबों:


553

बहुत आसान

//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);

25
यह वास्तव में कोड का एक अच्छा टुकड़ा है लेकिन यह उस तरह का कोड नहीं है जिसका उपयोग कहीं भी किया जा सकता है। डेवलपर्स को सावधान रहना चाहिए क्योंकि dirPath.Replace अवांछित परिणाम पैदा कर सकता है। बस लोगों को एक चेतावनी है कि नेट पर कॉपी और पेस्ट करना पसंद है। @Jayspired द्वारा पोस्ट किया गया कोड सुरक्षित है क्योंकि यह स्ट्रिंग का उपयोग नहीं करता है। लेकिन मुझे यकीन है कि इसके कोने मामले भी हैं।
एलेक्स

17
इस कोड के साथ सावधान रहें क्योंकि यह एक अपवाद फेंक देगा यदि लक्ष्य निर्देशिका पहले से मौजूद है। यह उन फ़ाइलों को भी अधिलेखित नहीं करेगा जो पहले से मौजूद हैं। बस प्रत्येक निर्देशिका बनाने से पहले एक जांच जोड़ें और यदि मौजूद है तो लक्ष्य फ़ाइल को अधिलेखित करने के लिए File.Copy के अधिभार का उपयोग करें।
जेरेज

30
@Xaisoft - Replaceएक समस्या है यदि आपके पास पथ के अंदर एक दोहराव पैटर्न है, उदाहरण के लिए "sourceDir/things/sourceDir/things"बन जाना चाहिए "destinationDir/things/sourceDir/things", लेकिन यदि आप इसका उपयोग करते हैं तो यह बन जाता है"destinationDir/things/destinationDir/things"
कीथ

35
*.*इसके बजाय क्यों *? क्या आप एक्सटेंशन के बिना भी फाइल कॉपी नहीं करना चाहते हैं?
डेरिल

10
चलो कुछ का निर्माण करें और इसे ओपन सोर्स .NET कोर में योगदान दें ...: /
Mnn

231

हम्म, मुझे लगता है कि मैं प्रश्न को गलत समझता हूं लेकिन मैं इसे जोखिम में डालने वाला हूं। निम्नलिखित सीधी विधि में क्या गलत है?

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));
}

EDIT चूंकि इस पोस्टिंग ने समान रूप से सरल प्रश्न के इतने सरल उत्तर के लिए एक प्रभावशाली संख्या में डाउनवॉट किया है, मुझे एक स्पष्टीकरण जोड़ना चाहिए। कृपया नीचे पढ़ने से पहले इसे पढ़ें

सबसे पहले, यह कोड प्रश्न में कोड को बदलने के लिए ड्रॉप-इन के रूप में इरादा नहीं है । यह केवल दृष्टांत प्रयोजन के लिए है।

Microsoft.VisualBasic.Devices.Computer.FileSystem.CopyDirectoryकुछ अतिरिक्त शुद्धता परीक्षण करता है (जैसे कि क्या स्रोत और लक्ष्य वैध निर्देशिका हैं, क्या स्रोत लक्ष्य का जनक है आदि) जो इस उत्तर से गायब हैं। वह कोड शायद अधिक अनुकूलित भी है।

उस ने कहा, कोड अच्छी तरह से काम करता है । यह है (लगभग हूबहू) साल के लिए एक परिपक्व सॉफ्टवेयर में इस्तेमाल किया गया। सभी आईओ हैंडलिंग के साथ मौजूद अंतर्निहित चंचलता के अलावा (जैसे कि क्या होता है यदि उपयोगकर्ता मैन्युअल रूप से यूएसबी ड्राइव को अनप्लग कर देता है जबकि आपका कोड इसे लिख रहा है?), कोई ज्ञात समस्या नहीं है।

विशेष रूप से, मैं यह बताना चाहता हूं कि यहाँ पुनरावृत्ति का उपयोग बिल्कुल समस्या नहीं है। न तो सिद्धांत में (वैचारिक रूप से, यह सबसे सुरुचिपूर्ण समाधान है) और न ही व्यवहार में: यह कोड स्टैक को अतिप्रवाह नहीं करेगा । स्टैक काफी बड़ा है, यहां तक ​​कि गहरी नेस्टेड फ़ाइल पदानुक्रमों को संभालने के लिए। स्टैक स्पेस की समस्या बनने से बहुत पहले, फ़ोल्डर पथ की लंबाई सीमा में किक हो जाती है।

ध्यान दें कि एक दुर्भावनापूर्ण उपयोगकर्ता एक -एक अक्षर के गहरे-नेस्टेड निर्देशिकाओं का उपयोग करके इस धारणा को तोड़ने में सक्षम हो सकता है। मैंने यह कोशिश नहीं की है। लेकिन बस इस बिंदु को स्पष्ट करने के लिए: इस कोड को एक विशिष्ट कंप्यूटर पर अतिप्रवाह करने के लिए, निर्देशिकाओं को कुछ हज़ार बार नेस्टेड करना होगा । यह बस एक यथार्थवादी परिदृश्य नहीं है।


5
यह हेड रिकरशन है। यह एक ढेर अतिप्रवाह का शिकार हो सकता है अगर निर्देशिकाओं को काफी गहरा घोंसला दिया जाए।
स्पॉल्सन

19
बहुत हाल तक, ओएस द्वारा डायरेक्टरी नेस्टिंग डेप्थ को प्रतिबंधित किया गया था। मुझे संदेह है कि आपको ऐसी निर्देशिकाएँ मिलेंगी जो कुछ सौ बार (यदि भी हों) से अधिक समय के लिए हों। उपरोक्त कोड बहुत अधिक ले सकता है ।
कोनराड रुडोल्फ

5
मुझे पुनरावर्ती दृष्टिकोण पसंद है, स्टैक ओवरफ्लो का जोखिम सबसे कम से कम है।
डेविड बसरब

49
@Dashkinov: अच्छी तरह से मुझे माफ करना, लेकिन यह एक बालक अत्यधिक लगता है। स्पष्ट कोड == डाउनवोट क्यों है? विपरीत सच होना चाहिए। अंतर्निहित विधि पहले से ही पोस्ट की गई थी, लेकिन कीथ ने विशेष रूप से दूसरी विधि के लिए कहा । इसके अलावा, आपके अंतिम वाक्य का क्या मतलब है? क्षमा करें, लेकिन मैं आपके पतन के कारणों को बिलकुल नहीं समझता।
कोनराड रूडोल्फ

6
@ इमिसिको: किस से बेहतर ? किसी ने भी फ्रेमवर्क से वीबी कोड से बेहतर होने का दावा नहीं किया। हम जानते हैं कि यह नहीं है।
कोनराड रुडोल्फ

131

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.
}

8
यदि निर्देशिका मौजूद है, तो जाँच करने का कोई कारण नहीं है, बस Directoty.CreateDirectory को कॉल करें जो कि निर्देशिका पहले से मौजूद है तो कुछ भी नहीं करेगा।
ताल जेरोम

1
256 से अधिक वर्णों के रास्तों से निपटने के इच्छुक लोगों के लिए, आप ZetaLongPaths नामक एक Nuget पैकेज का उपयोग कर सकते हैं
AK

2
यह उत्तर उन सभी में सबसे अधिक उपयोगी लगता है। स्ट्रिंग्स के बजाय DirectoryInfo का उपयोग करके बहुत सारी संभावित समस्याओं से बचा जाता है।
DaedalusAlpha

50

इसे इस्तेमाल करे:

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 तर्क भिन्न हो सकते हैं लेकिन आपको विचार मिलता है।


3
/ ई इसे सभी उप निर्देशिकाओं (यहां तक ​​कि खाली वाले) को कॉपी करने के लिए कहता है। / मैं इसे बताता हूं कि यदि गंतव्य मौजूद नहीं है तो उस नाम के साथ एक निर्देशिका बनाएं।
d4nt

6
सुरक्षित होने के लिए दोहरे उद्धरण जोड़ें।
jaysonragasa

6
मौजूदा फ़ाइलों को अधिलेखित करने के लिए प्रेरित होने से रोकने के लिए / Y जोड़ें। stackoverflow.com/q/191209/138938
जॉन क्राउन

16
क्षमा करें, लेकिन यह भयानक है। यह मानता है कि लक्ष्य प्रणाली विंडोज़ है। यह मानता है कि भविष्य के संस्करणों में उस विशिष्ट पथ पर xcopy.exe शामिल है। यह मानता है कि xcopy के पैरामीटर नहीं बदलते हैं। यह स्ट्रिंग के रूप में xcopy के लिए मापदंडों को इकट्ठा करने की आवश्यकता है, जो त्रुटि क्षमता का बहुत परिचय देता है। इसके अलावा नमूना शुरू की गई प्रक्रिया के परिणामों के लिए किसी भी त्रुटि से निपटने का उल्लेख नहीं करता है, जो मुझे उम्मीद होगी, क्योंकि अन्य तरीकों के विपरीत यह चुपचाप विफल हो जाएगा।
cel sharp

3
@MatthiasJansen, मुझे लगता है कि आपने इसे बहुत व्यक्तिगत लिया। इसका उत्तर इस बिंदु पर है और इसे कैसे प्राप्त किया जाए, इसके बारे में बहुत कुछ बताया गया है ... क्योंकि प्रश्न में क्रॉस प्लेटफ़ॉर्म संगतता की मांग नहीं है या xcopy या किसी अन्य चीज़ का उपयोग नहीं किया गया है, पोस्टर ने केवल यह समझाने के लिए उत्तर दिया है कि यह एक तरह से कैसे प्राप्त किया जा सकता है ... वहाँ एक ही काम करने के 1000 तरीके हो सकते हैं और उत्तर अलग-अलग हो सकते हैं .. यही कारण है कि यह मंच यहां संबोधित करने के लिए है और दुनिया भर के प्रोग्रामर यहां अपने अनुभव साझा करने के लिए आते हैं। मैं आपकी टिप्पणी को अस्वीकार करता हूं।
केएमएक्स

47

या, यदि आप कठिन रास्ते पर जाना चाहते हैं, तो Microsoft के लिए अपनी परियोजना के लिए एक संदर्भ जोड़ें। विवादास्पद और फिर निम्नलिखित का उपयोग करें:

Microsoft.VisualBasic.FileIO.FileSystem.CopyDirectory(fromDirectory, toDirectory);

हालाँकि, पुनरावर्ती कार्यों में से एक का उपयोग करना एक बेहतर तरीका है क्योंकि इसे VB dll को लोड नहीं करना होगा।


1
यह वास्तव में अलग नहीं है कि मैंने इसे वैसे भी कैसे किया - आपको अभी भी इसे करने में सक्षम होने के लिए वीबी के पिछड़े-अनुकूलता वाले सामान को लोड करने की आवश्यकता है।
कीथ

10
क्या VB असेंबली लोड करना महंगा है? VB विकल्प C # संस्करणों की तुलना में बहुत अधिक सुरुचिपूर्ण हैं।
jwmiller5

3
"वीबी के पिछड़े-अनुकूलता वाले सामान" क्या हैं? CopyDirectory शेल या फ्रेमवर्क का उपयोग करती है।
एमीसिको

3
मैं चाहता हूं कि यह चालू था System.IO.Directory, लेकिन इसे फिर से लिखने से बेहतर है!
जोश एम।

2
यह इमो जाने का तरीका है, अन्य विकल्पों में से किसी भी विकल्प की तुलना में बहुत आसान है
रेगेगिटेर

38

इस साइट ने हमेशा मुझे बहुत मदद की है, और अब यह मेरी बारी है कि मैं जो जानता हूं उसके साथ दूसरों की मदद करूं।

मुझे उम्मीद है कि नीचे दिया गया मेरा कोड किसी के लिए उपयोगी होगा।

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)));
    }

1
पीछे आने वाली याद के बारे में याद रखें
एलेक्सी एफ

24
फोल्क्स, उपयोग Path.Combine()। फ़ाइल पथ को एक साथ रखने के लिए स्ट्रिंग स्ट्रिंग का उपयोग कभी न करें।
एंडी १

3
आपको उपरोक्त कोड स्निपेट में एक OBOB है। आपको उपयोग करना चाहिए source_dir.Length + 1, न कि source_dir.Length
पेलुसीडॉम्बैट

यह कोड एक अच्छी अवधारणा है, लेकिन ... एक फ़ाइल के लिए "" होना आवश्यक नहीं है। इसमें, इसलिए ystem.IO.Directory.GetFiles (source_dir, "*", System.IO.SearchOption.AllDirectories) का उपयोग करना बेहतर होगा।)
जीन

धन्यवाद @JeanLibera, आप सही हैं। मैंने आपके सुझाव से कोड बदल दिया है।
जयप्रकाश

14

स्टैक ओवरफ़्लो से बचने के लिए पुनरावर्ती के बिना पुनरावर्ती फ़ोल्डर कॉपी करें।

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;
    }
}

उपयोगी गैर-पुनरावृत्ति टेम्पलेट :)
मिन्ह गुयेन

2
पथ सीमा को
एड एस।

5

यहाँ एक उपयोगिता वर्ग है जिसका उपयोग मैंने 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;
        }
    }
}

ध्यान दें कि Microsoft, Microsoft के लिए आंतरिक रूप से SHFileOperation का उपयोग करता है।
jrh

3

यह प्रदर्शन-जागरूक नहीं हो सकता है, लेकिन मैं इसे 30 एमबी फ़ोल्डर के लिए उपयोग कर रहा हूं और यह त्रुटिपूर्ण रूप से काम करता है। इसके अलावा, मैं इस तरह के एक आसान काम के लिए आवश्यक सभी कोड और पुनरावृत्ति पसंद नहीं करता था।

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);

नोट: ZipFile System.IO.Compression नामस्थान में .NET 4.5+ पर उपलब्ध है


1
न तो मैं, इसलिए सवाल, लेकिन चयनित जवाब पुनरावृत्ति की आवश्यकता नहीं है। यह उत्तर डिस्क पर एक ज़िप फ़ाइल बनाता है, जो एक फ़ाइल कॉपी के लिए बहुत सारे अतिरिक्त काम है - न केवल आप डेटा की एक अतिरिक्त प्रतिलिपि बना रहे हैं, लेकिन आप प्रोसेसर समय को कम करने और इसे कम करने में खर्च कर रहे हैं। मुझे यकीन है कि यह काम करता है, उसी तरह आप शायद अपने जूते के साथ एक कील ठोक सकते हैं, लेकिन यह अधिक चीजों के साथ अधिक काम है जो गलत हो सकता है, जबकि इसे करने के बेहतर तरीके हैं।
कीथ

इसका कारण जो मैंने समाप्त किया वह स्ट्रिंग प्रतिस्थापन है। जैसा कि दूसरों ने बताया है, स्वीकृत जवाब कई चिंताओं को प्रस्तुत करता है; जंक्शन लिंक काम नहीं कर सकता, साथ ही विस्तार या नाम के बिना फ़ोल्डर पैटर्न या फ़ाइलों को दोहरा सकता है। कम कोड, गलत होने की कम संभावना। और चूंकि प्रोसेसर का समय मेरे लिए चिंता का विषय नहीं है, इसलिए यह मेरे विशिष्ट मामले के लिए उपयुक्त है
अलेक्जेंडर

2
हाँ, यह एक ट्रैफिक लाइट से बचने के लिए 1000 मील की दूरी पर गाड़ी चलाने जैसा है, लेकिन यह आपकी यात्रा है, इसलिए इसके लिए जाएं। फोल्डर पैटर्न के लिए जाँच करना ज़िप की तुलना में तुच्छ है जो हुड के नीचे करने की आवश्यकता है। मैं इसके लिए दृढ़ता से अनुशंसा करता हूं कि कोई भी जो प्रोसेसर, डिस्क, बिजली बर्बाद नहीं करता है या जहां यह एक ही मशीन पर अन्य कार्यक्रमों के साथ चलाने की आवश्यकता है। इसके अलावा, अगर आपसे कभी भी इस प्रकार का प्रश्न पूछा जाता है तो साक्षात्कार में कभी भी "मेरा कोड सरल नहीं होता है इसलिए मुझे प्रोसेसर समय की परवाह नहीं है" - आपको काम नहीं मिलेगा।
कीथ

1
मैंने @ justin-r द्वारा दिए गए उत्तर पर स्विच किया । फिर भी, मैं इस उत्तर को वहाँ करने के दूसरे तरीके के रूप में छोड़ दूँगा
अलेक्जेंडरड

1
यदि फ़ोल्डर अलग-अलग नेटवर्क शेयरों पर हैं और बहुत सारी फाइलें हैं, तो मेरी राय में यह सबसे अच्छा विकल्प होगा।
डैनी पार्कर

2

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));
    }
}

2

यह मेरी कोड आशा है कि यह मदद करेगा

    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;
    }

चयनित उत्तर को देखें, SearchOptionफ़ोल्डर और फ़ाइलों की खोजों पर ध्वज का उपयोग करके यह कोड की 4 पंक्तियों में करता है। इसके अलावा .HasFlagअब एनम पर विस्तार की जाँच करें ।
कीथ

2

यदि आपको कोनराड का लोकप्रिय उत्तर पसंद है, लेकिन आप चाहते हैं कि यह 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;
}

2

तुम हमेशा उपयोग कर सकते हैं इस , माइक्रोसॉफ्ट के वेबसाइट से लिया।

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);
        }
    }
}

1
यह बहुत अच्छा है - यह ध्यान रखें कि रेखा file.CopyTo(temppath, false);कहती है "इस फ़ाइल को इस स्थान पर कॉपी करें, केवल अगर यह मौजूद नहीं है", जो कि ज्यादातर समय वह नहीं है जो हम चाहते हैं। लेकिन, मैं समझ सकता हूं कि यह उस पर चूक क्यों करता है। शायद फ़ाइलों को अधिलेखित करने के लिए विधि में एक ध्वज जोड़ें।
एंडी १

2

tboswell के प्रूफ संस्करण को बदलें (जो फ़ाइलपथ में पैटर्न को दोहराने के लिए लचीला है)

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);
    }

3
फोल्क्स, उपयोग Path.Combine()। फ़ाइल पथ को एक साथ रखने के लिए स्ट्रिंग स्ट्रिंग का उपयोग कभी न करें।
एंडी १

2

मेरा समाधान मूल रूप से @ टर्मिनिनजा के उत्तर का एक संशोधन है, हालांकि मैंने इसे थोड़ा बढ़ाया है और यह स्वीकृत उत्तर की तुलना में 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 को पूर्ण समानांतर फ़ॉर्च में संशोधित करने से बेहतर परिणाम प्राप्त होता है, हालांकि कोड पुनरावर्ती फ़ंक्शन का उपयोग करता है और कुछ स्थिति में इसका आदर्श नहीं है।

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));
}

1

पिछले कोड के लिए क्षमा करें, इसमें अभी भी बग थे :( (सबसे तेज बंदूक की समस्या का शिकार हो गया)। यहां इसका परीक्षण और काम किया जा रहा है। कुंजी 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);
    }
}

1

यहाँ DirectoryInfo के लिए एक एक्सटेंशन विधि है एक 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;
}

1

इस वर्ग का उपयोग करें।

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);
    }
}

1
यह अन्य उत्तरों के समान है, .ToList().ForEach(जिसका उपयोग करने के लिए रिफलेक्ट किया गया है (जो सीधे निर्देशिकाओं की गणना करने की तुलना में थोड़ा अधिक काम, स्मृति और थोड़ा धीमा है) और एक विस्तार विधि के रूप में। चयनित जवाब का उपयोग करता है SearchOption.AllDirectoriesऔर टाल प्रत्यावर्तन, इसलिए मुझे लगता है कि मॉडल का उपयोग करने जा सलाह देते हैं। इसके अलावा, आपको आमतौर पर विस्तार विधियों में टाइप के नाम की आवश्यकता नहीं होती है - मैं इसका नाम बदल कर CopyTo()sourceDir.CopyTo(destination);
कीथ

1

सभी फ़ोल्डर और फ़ाइलों की प्रतिलिपि के लिए केवल एक लूप वाला एक संस्करण:

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);
}

यदि आप उपयोग करने जा रहे हैं Regex, तो आपको Regex.Escape(path)अपनी अभिव्यक्ति रचना (विशेष रूप से विंडोज पथ विभाजक पर विचार) के हिस्से के रूप में भी होना चाहिए । आप कर सकते हैं भी बनाने (और शायद संकलन) एक से लाभ प्राप्त new Regex()पाश की वस्तु के बाहर के बजाय स्थिर पद्धति पर भरोसा करता है।
jimbobmcgee

0

किसी भी कोड की तुलना में बेहतर है (पुनरावृत्ति के साथ DirectoryInfo के लिए विस्तार विधि)

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;
        }
    }

1
मुझे यकीन नहीं है कि यह स्वीकार किए गए उत्तर पर क्या जोड़ता है, रिकर्सन का उपयोग करने के अलावा (जहां इसकी आवश्यकता नहीं है) और डिबगिंग को कठिन बनाने के लिए अपवादों को छिपाते हैं।
कीथ

0

फ़ोल्डर की सभी फ़ाइलों को कॉपी और बदलें

        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);
            }
    }

उत्तर के लिए चीयर्स, लेकिन मुझे यकीन नहीं है कि यह क्या जोड़ता है। इसके अलावा try catch throwव्यर्थ है।
कीथ

0

नीचे दिए गए कोड माइक्रोसॉफ्ट सुझाव है कि कैसे करने के लिए कॉपी-निर्देशिका और यह प्रिय द्वारा साझा किया जाता @iato लेकिन यह सिर्फ प्रतियां उप निर्देशिका और रिकर्सिवली स्रोत फ़ोल्डर की फ़ाइलों और यह स्वयं फ़ोल्डर स्रोत नकल नहीं करता है (राइट क्लिक तरह -> प्रतिलिपि )।

लेकिन इस जवाब के नीचे एक मुश्किल तरीका है :

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));

नीचे पहले से ही कुछ उत्तर पोस्ट किए गए हैं: stackoverflow.com/a/45199038/1951524
मार्टिन श्नाइडर

धन्यवाद @ एमए-मैडिन, लेकिन क्या यह स्रोत फ़ोल्डर की प्रतिलिपि बनाता है? या सिर्फ सामग्री?
अराश.जंडी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.