Chcę skopiować całą zawartość katalogu z jednej lokalizacji do drugiej w C #.
Wydaje się, że nie ma sposobu, aby to zrobić za pomocą System.IO
klas bez dużej rekurencji.
W VB istnieje metoda, której możemy użyć, jeśli dodamy odwołanie do Microsoft.VisualBasic
:
new Microsoft.VisualBasic.Devices.Computer().
FileSystem.CopyDirectory( sourceFolder, outputFolder );
To wydaje się raczej brzydkim hackem. Czy jest lepszy sposób?
Microsoft.VisualBasic
a nieSystem.IO
? Powodem, dla którego nie ma go w Mono, jest to, że wszystkie biblioteki uważane za „podstawowe” sąSystem.[something]
- wszystkie inne nie. Nie mam problemu z powołaniem się na dodatkową bibliotekę DLL, ale jest dobry powód, dla którego Microsoft nie zawarł tej funkcjiSystem.IO
.Odpowiedzi:
Dużo łatwiej
źródło
Replace
ma problem, jeśli masz powtarzający się wzór na ścieżce, na przykład"sourceDir/things/sourceDir/things"
powinien się stać"destinationDir/things/sourceDir/things"
, ale jeśli użyjesz zamień, staje się"destinationDir/things/destinationDir/things"
*.*
zamiast*
? Nie chcesz też kopiować plików bez rozszerzeń?Hmm, chyba nie rozumiem pytania, ale zaryzykuję. Co jest nie tak z następującą prostą metodą?
EDYCJA Ponieważ ten post zebrał imponującą liczbę głosów negatywnych za tak prostą odpowiedź na równie proste pytanie, pozwól mi dodać wyjaśnienie. Proszę przeczytać przed downvoting .
Przede wszystkim ten kod nie jest zamiennikiem zastępującym kod w pytaniu. To jest wyłącznie w celach ilustracyjnych.
Microsoft.VisualBasic.Devices.Computer.FileSystem.CopyDirectory
wykonuje dodatkowe testy poprawności (np. czy źródło i cel są poprawnymi katalogami, czy źródło jest rodzicem celu itp.), których brakuje w tej odpowiedzi. Ten kod jest prawdopodobnie również bardziej zoptymalizowany.To powiedziawszy, kod działa dobrze . To jest (prawie identycznie) zostały wykorzystane w dojrzałym oprogramowania przez lata. Oprócz nieodłącznej zmienności występującej we wszystkich operacjach we / wy (np. Co się stanie, jeśli użytkownik ręcznie odłączy dysk USB podczas pisania na nim kodu?), Nie ma znanych problemów.
W szczególności chciałbym zwrócić uwagę, że zastosowanie rekurencji tutaj absolutnie nie stanowi problemu. Ani w teorii (koncepcyjnie jest to najbardziej eleganckie rozwiązanie), ani w praktyce: ten kod nie przepełni stosu . Stos jest wystarczająco duży, aby obsłużyć nawet głęboko zagnieżdżone hierarchie plików. Na długo przed pojawieniem się problemu ze stosem zaczyna się ograniczenie długości ścieżki folderu.
Zauważ, że złośliwy użytkownik może złamać to założenie, używając głęboko zagnieżdżonych katalogów po jednej literze. Nie próbowałem tego. Ale żeby to zilustrować: aby przepełnić ten kod na typowym komputerze, katalogi musiałyby być zagnieżdżone kilka tysięcy razy. To po prostu nie jest realistyczny scenariusz.
źródło
Skopiowano z MSDN :
źródło
Spróbuj tego:
Twoje argumenty xcopy mogą się różnić, ale masz pomysł.
źródło
Lub, jeśli chcesz pójść na poważnie, dodaj odniesienie do swojego projektu dla Microsoft.VisualBasic, a następnie użyj następujących poleceń:
Jednak korzystanie z jednej z funkcji rekurencyjnych jest lepszym sposobem, ponieważ nie trzeba ładować biblioteki DLL VB.
źródło
System.IO.Directory
, ale to lepsze niż przepisywanie!Ta strona zawsze bardzo mi pomogła, a teraz moja kolej, aby pomóc innym w tym, co wiem.
Mam nadzieję, że mój poniższy kod będzie dla kogoś przydatny.
źródło
Path.Combine()
. Nigdy nie używaj konkatenacji ciągów do łączenia ścieżek plików.source_dir.Length + 1
, niesource_dir.Length
.Skopiuj folder rekurencyjnie bez rekurencji, aby uniknąć przepełnienia stosu.
źródło
Oto klasa narzędzi, której użyłem do takich zadań IO.
źródło
Może nie jest świadomy wydajności, ale używam go do folderów 30 MB i działa bezbłędnie. Poza tym nie podobała mi się cała ilość kodu i rekursji wymagana do tak łatwego zadania.
Uwaga: ZipFile jest dostępny w .NET 4.5+ w przestrzeni nazw System.IO.Compression
źródło
Drobne ulepszenie odpowiedzi d4nt, ponieważ prawdopodobnie chcesz sprawdzić błędy i nie musisz zmieniać ścieżek xcopy, jeśli pracujesz na serwerze i komputerze programistycznym:
źródło
To jest mój kod, mam nadzieję, że ta pomoc
źródło
SearchOption
flagi przy wyszukiwaniu folderów i plików, robi to w 4 liniach kodu. Sprawdź również.HasFlag
rozszerzenie teraz na wyliczeniach.Jeśli podoba Ci się popularna odpowiedź Konrada, ale chcesz, aby
source
sam był folderem podtarget
, zamiast umieszczać w nim swoje dziecitarget
, oto kod do tego. Zwraca nowo utworzonyDirectoryInfo
, co jest przydatne:źródło
Zawsze możesz tego użyć , pobranego ze strony Microsofts.
źródło
file.CopyTo(temppath, false);
napisane „skopiuj ten plik do tego miejsca, tylko jeśli nie istnieje”, co w większości przypadków nie jest tym, czego chcemy. Ale rozumiem, dlaczego to domyślnie. Może dodać flagę do metody zastępowania plików.tboswell's replace Proof version (który jest odporny na powtarzanie wzorca w ścieżce pliku)
źródło
Path.Combine()
. Nigdy nie używaj konkatenacji ciągów do łączenia ścieżek plików.Moje rozwiązanie jest w zasadzie modyfikacją odpowiedzi @ Termininja, jednak nieco ją ulepszyłem i wydaje się, że jest ponad 5 razy szybsza niż zaakceptowana odpowiedź.
EDYCJA: Modyfikacja @Ahmed Sabry do pełnego równoległego foreach daje lepszy wynik, jednak kod używa funkcji rekurencyjnej i w niektórych sytuacjach nie jest idealny.
źródło
Przepraszamy za poprzedni kod, nadal miał błędy :( (padł ofiarą problemu z najszybszym działem). Tutaj jest testowany i działa. Kluczem jest SearchOption.AllDirectories, co eliminuje potrzebę wyraźnej rekursji.
źródło
Oto metoda rozszerzenia DirectoryInfo a la FileInfo.CopyTo (zwróć uwagę na
overwrite
parametr):źródło
Użyj tej klasy.
źródło
.ToList().ForEach(
(co jest nieco więcej pracy, pamięci i nieco wolniej niż tylko bezpośrednie wyliczanie katalogów) i jako metoda rozszerzenia. Wybrana odpowiedź używaSearchOption.AllDirectories
rekurencji i unika jej, więc polecam przejście na ten model. Ponadto zwykle nie potrzebujesz nazwy typu w metodach rozszerzenia - zmieniłem nazwę na,CopyTo()
aby stała sięsourceDir.CopyTo(destination);
Jeden wariant z tylko jedną pętlą do kopiowania wszystkich folderów i plików:
źródło
Regex
, prawdopodobnie powinieneś równieżRegex.Escape(path)
stanowić część kompozycji wyrażenia (szczególnie biorąc pod uwagę separator ścieżek systemu Windows). Państwo może również uzyskać korzyści z tworzenia (a może kompilacji) nanew Regex()
zewnątrz obiektu pętli, a nie opierając się na metodzie statycznej.Lepszy niż jakikolwiek kod (metoda rozszerzenia DirectoryInfo z rekurencją)
źródło
Skopiuj i zamień wszystkie pliki w folderze
źródło
try
catch
throw
ma sensu.Poniższy kod jest sugestią Microsoft dotyczącą kopiowania katalogów i jest udostępniany przez drogi @iato, ale kopiuje tylko podkatalogi i pliki folderu źródłowego rekurencyjnie i nie kopiuje folderu źródłowego samodzielnie (jak kliknięcie prawym przyciskiem myszy -> kopiowanie ).
ale pod tą odpowiedzią jest trudny sposób :
jeśli chcesz skopiować zawartość z źródłowego folderu i podfolderów rekurencyjnie można po prostu używać go tak:
ale jeśli chcesz skopiować katalog źródłowy samodzielnie (podobnie, jak kliknąłeś folder źródłowy i kliknąłeś kopię, a następnie w folderze docelowym kliknąłeś wklej), powinieneś użyć w ten sposób:
źródło