Wygląda na to, że cp nie jest wywołaniem systemowym i dlatego nie należy do modułu os. Jest to polecenie powłoki, dlatego zostało umieszczone w module shutil.
waldol1
Odpowiedzi:
3005
shutilma wiele metod, których możesz użyć. Jednym z nich jest:
from shutil import copyfile
copyfile(src, dst)
Skopiuj zawartość pliku o nazwie src do pliku o nazwie dst .
Lokalizacja docelowa musi być zapisywalna; w przeciwnym razie zostanie zgłoszony wyjątek IOError .
Jeśli dst już istnieje, zostanie zastąpione.
Za pomocą tej funkcji nie można kopiować plików specjalnych, takich jak urządzenia znakowe lub blokowe oraz potoki.
W przypadku copy , src i dst są nazwami ścieżek podanymi jako ciągi znaków .
Jeśli korzystasz z os.pathoperacji, użyj copyraczej niż copyfile. copyfilebędzie akceptować tylko ciągi .
Jaka jest różnica między kopiowaniem a plikiem kopiowania?
Matt
385
w copy (src, dst) dst może być katalogiem.
Owen
41
Pamiętaj, że nie wszystkie metadane zostaną skopiowane, w zależności od platformy.
Kevin Horn
12
Pamiętaj, że nie jest to operacja atomowa. Uważaj, używając go w aplikacji wątkowej.
waterbyte
4
Należy pamiętać, że nie może obsługiwać skrótów takich jak ~, ale może radzić sobie ze ścieżkami względnymi
zwep
1251
┌──────────────────┬────────┬───────────┬───────┬────────────────┐
│ Function │ Copies │ Copies │Can use│ Destination │
│ │metadata│permissions│buffer │may be directory│
├──────────────────┼────────┼───────────┼───────┼────────────────┤
│shutil.copy │ No │ Yes │ No │ Yes │
│shutil.copyfile │ No │ No │ No │ No │
│shutil.copy2 │ Yes │ Yes │ No │ Yes │
│shutil.copyfileobj│ No │ No │ Yes │ No │
└──────────────────┴────────┴───────────┴───────┴────────────────┘
Próbuję losowo skopiować 100 000 plików z 1 miliona plików. copyfilejest znacznie szybszy niżcopy2
Vijay
4
czy słusznie zakładam, że shutil.copy2('/dir/file.ext', '/new/dir/')(z ukośnikiem za ścieżką docelową) usunie dwuznaczność, czy skopiować do nowego pliku o nazwie „katalog”, czy umieścić plik w katalogu o tej nazwie?
Zak.
1
@Vijay Uważam, że narzut ten wynika z kopiowania metadanych.
Jonathan H
@Zak Nie ma dwuznaczności, jeśli /new/diristnieje katalog, patrz komentarz @ MatthewAlpert.
Jonathan H
@Zak Masz rację, dodanie ukośnika na końcu usuwa dwuznaczność. Jeśli /new/dir/nie istnieje, Python rzuci an IsADirectoryError, w przeciwnym razie kopiuje plik do /new/dir/oryginalnej nazwy.
martonbognar
125
Możesz użyć jednej z funkcji kopiowania z shutilpakietu:
@lightalchemist Właśnie użyłem vima jako scratchpada, skopiowałem używane symbole Unicode z tabeli wikipedii i skopiowałem wynik do edytora stackoverflow w celu ostatecznego polerowania.
@wim, musisz porównać moją odpowiedź z wersją 2017, którą podałeś, która była aktualna, kiedy opublikowałem moją odpowiedź. Główne różnice: moja odpowiedź wykorzystuje lepsze / bardziej opisowe nagłówki kolumn, układ tabeli nie rozprasza, zawiera bezpośrednie linki do dokumentacji i dodałem kolumnę (tzn. „Akceptuje plik obj”).
maxschlepzig
4
OK. YMMV, ale myślę, że zmiany kosmetyczne i takie drobne ulepszenia lepiej wprowadzać jako modyfikacje istniejących odpowiedzi, niż powielania odpowiedzi.
os.popen(cmd[, mode[, bufsize]])# example# In Unix/Linux
os.popen('cp source.txt destination.txt')# In Windows
os.popen('copy source.txt destination.txt')
subprocess.call(args,*, stdin=None, stdout=None, stderr=None, shell=False)# example (WARNING: setting `shell=True` might be a security-risk)# In Linux/Unix
status = subprocess.call('cp source.txt destination.txt', shell=True)# In Windows
status = subprocess.call('copy source.txt destination.txt', shell=True)
subprocess.check_output(args,*, stdin=None, stderr=None, shell=False, universal_newlines=False)# example (WARNING: setting `shell=True` might be a security-risk)# In Linux/Unix
status = subprocess.check_output('cp source.txt destination.txt', shell=True)# In Windows
status = subprocess.check_output('copy source.txt destination.txt', shell=True)
Używanie poleceń jednołańcuchowych jest złym stylem kodowania (elastyczność, niezawodność i bezpieczeństwo), zamiast tego używaj ['copy', sourcefile, destfile]składni tam, gdzie to możliwe, szczególnie jeśli parametry pochodzą z danych wprowadzonych przez użytkownika.
Marcel Waldvogel
8
Dlaczego wymieniasz tak wiele złych alternatyw dla funkcji kopiowania shutil?
maxschlepzig
6
Shutil jest wbudowany, nie ma potrzeby oferowania nieprzenośnych alternatyw. Odpowiedź można poprawić, usuwając rozwiązania zależne od systemu, a po usunięciu ta odpowiedź jest tylko kopią istniejących odpowiedzi / kopią dokumentacji.
Jean-François Fabre
3
os.popenjest przez pewien czas przestarzałe. i check_outputnie zwraca statusu, ale wyjście (które jest puste w przypadku copy/cp)
Jean-François Fabre
2
shutil nie kopiuje plików. U góry dokumentów znajduje się duże ostrzeżenie o tłuszczu . „oznacza to, że właściciel pliku i grupa zostaną utracone, a także listy ACL. W systemie Mac OS rozwidlenie zasobów i inne metadane nie są używane. Oznacza to, że zasoby zostaną utracone, a typy plików i kody twórców będą nieprawidłowe. W systemie Windows, właściciele plików, listy ACL i alternatywne strumienie danych nie są kopiowane. ”
gman
96
Kopiowanie pliku jest stosunkowo prostą operacją, jak pokazano w poniższych przykładach, ale zamiast tego powinieneś użyć do tego modułu shutil stdlib .
def copyfileobj_example(source, dest, buffer_size=1024*1024):"""
Copy a file from source to dest. source and dest
must be file-like objects, i.e. any object with a read or
write method, like for example StringIO.
"""whileTrue:
copy_buffer = source.read(buffer_size)ifnot copy_buffer:break
dest.write(copy_buffer)
Jeśli chcesz skopiować według nazwy pliku, możesz zrobić coś takiego:
def copyfile_example(source, dest):# Beware, this example does not handle any edge cases!with open(source,'rb')as src, open(dest,'wb')as dst:
copyfileobj_example(src, dst)
Jakiś czas temu zauważyłem, że moduł nazywa się shutil (liczba pojedyncza), a nie shutils (liczba mnoga), i rzeczywiście jest w Pythonie 2.3. Niemniej jednak zostawiam tę funkcję tutaj jako przykład.
pi.
4
Kopiowanie zawartości pliku jest prostą operacją. Kopiowanie pliku z jego metadanymi nie jest proste, tym bardziej, jeśli chcesz być wieloplatformowy.
LaC
3
Prawdziwe. Patrząc na dokumenty shutil, funkcja copyfile również nie kopiuje metadanych.
pi.
3
Tak, nie jestem pewien, dlaczego po prostu nie skopiujesz źródła shutil.copyfileobj. Ponadto nie musisz try, finallyzajmować się zamykaniem plików po wyjątkach. Powiedziałbym jednak, że twoja funkcja nie powinna w ogóle odpowiadać za otwieranie i zamykanie plików. Powinno to przebiegać w funkcji otoki, np. Jak shutil.copyfileotacza shutil.copyfileobj.
ErlVolton
2
Powyższy kod powinien określać, że destma być zapisywalny:open(dest, 'wb')
Skopiuj zawartość pliku o nazwie src do pliku o nazwie dst. Lokalizacja docelowa musi być zapisywalna; w przeciwnym razie zostanie zgłoszony wyjątek IOError. Jeśli dst już istnieje, zostanie zastąpione. Za pomocą tej funkcji nie można kopiować plików specjalnych, takich jak urządzenia znakowe lub blokowe oraz potoki. src i dst to nazwy ścieżek podane jako ciągi znaków.
Spójrz na system plików dla wszystkich funkcji obsługi plików i katalogów dostępnych w standardowych modułach Python.
shutil nie kopiuje plików. U góry dokumentów znajduje się duże ostrzeżenie o tłuszczu . „oznacza to, że właściciel pliku i grupa zostaną utracone, a także listy ACL. W systemie Mac OS rozwidlenie zasobów i inne metadane nie są używane. Oznacza to, że zasoby zostaną utracone, a typy plików i kody twórców będą nieprawidłowe. W systemie Windows, właściciele plików, listy ACL i alternatywne strumienie danych nie są kopiowane. ”
gman
47
Przykład skopiowania katalogu i pliku - z Tima Golden'a w Pythonie:
shutil nie kopiuje plików. U góry dokumentów znajduje się duże ostrzeżenie o tłuszczu . „oznacza to, że właściciel pliku i grupa zostaną utracone, a także listy ACL. W systemie Mac OS rozwidlenie zasobów i inne metadane nie są używane. Oznacza to, że zasoby zostaną utracone, a typy plików i kody twórców będą nieprawidłowe. W systemie Windows, właściciele plików, listy ACL i alternatywne strumienie danych nie są kopiowane. ”
gman
19
W przypadku małych plików i korzystania tylko z wbudowanych Pythona można użyć następującego jednowierszowego:
with open(source,'rb')as src, open(dest,'wb')as dst: dst.write(src.read())
Jak wspomniano w komentarzach @maxschlepzig, nie jest to optymalny sposób dla aplikacji, w których plik jest zbyt duży lub gdy pamięć jest krytyczna, dlatego należy preferować odpowiedź Swati .
Odczytuje pełny plik źródłowy do pamięci przed jego ponownym zapisaniem. W ten sposób niepotrzebnie marnuje się pamięć na wszystkie operacje kopiowania plików oprócz najmniejszych.
maxschlepzig
1
Czy to prawda? Myślę, że .read()i .write()są buforowane domyślnie (przynajmniej dla CPython).
soundstripe
@soundstripe, Oczywiście to prawda. Fakt, że obiekt pliku zwracany przez open()buforuje IO, domyślnie nie pomaga tutaj, ponieważ read()jest określony jako: „Jeśli n jest ujemne lub pominięte, czytaj do EOF”. Oznacza to, że read()zwraca całą zawartość pliku jako ciąg.
maxschlepzig
@maxschlepzig Rozumiem twój punkt widzenia i przyznaję, że nie byłem tego świadomy. Podałem tę odpowiedź na wypadek, gdyby ktoś chciał zrobić prostą kopię pliku przy użyciu tylko wbudowanych elementów, bez potrzeby importowania modułu. Oczywiście optymalizacja pamięci nie powinna być problemem, jeśli chcesz tę opcję. W każdym razie dziękuję za wyjaśnienie tego. Odpowiednio zaktualizowałem odpowiedź.
nie jest to przenośne i niepotrzebne, ponieważ można po prostu użyć shutil.
Corey Goldberg,
4
Nawet gdy shutilnie jest dostępny - subprocess.run() (bez shell=True!) Jest lepszą alternatywą dla os.system().
maxschlepzig
1
Shutil jest bardziej przenośny
Hiadore,
1
subprocess.run()jak sugeruje @maxschlepzig, to duży krok naprzód w przypadku wywoływania programów zewnętrznych. Jednak w celu zapewnienia elastyczności i bezpieczeństwa użyj ['cp', rawfile, 'rawdata.dat']formularza przekazania wiersza polecenia. (Jednak w przypadku kopiowania shutilzaleca się , aby znajomi zamiast wywoływać program zewnętrzny).
Marcel Waldvogel,
2
spróbuj tego z nazwami plików ze spacjami.
Jean-François Fabre
11
W przypadku dużych plików zrobiłem to, czytając plik linia po linii i czytając każdą linię w tablicy. Następnie, gdy tablica osiągnie określony rozmiar, dołącz ją do nowego pliku.
for line in open("file.txt","r"):
list.append(line)if len(list)==1000000:
output.writelines(list)del list[:]
wydaje się to trochę zbędne, ponieważ pisarz powinien obsługiwać buforowanie. for l in open('file.txt','r'): output.write(l)powinien znaleźć pracę; po prostu skonfiguruj bufor strumienia wyjściowego do swoich potrzeb. lub możesz przejść przez bajty, zapętlając próbę, output.write(read(n)); output.flush()gdzie njest liczba bajtów, którą chcesz zapisać na raz. oba z nich również nie mają warunku, aby sprawdzić, która premia.
jest właścicielem
1
Tak, ale pomyślałem, że może to być łatwiejsze do zrozumienia, ponieważ kopiuje całe wiersze, a nie ich części (na wypadek, gdybyśmy nie wiedzieli, ile bajtów to każda linia).
ytpillai
Bardzo prawdziwe. Kodowanie do nauczania i kodowanie dla wydajności są bardzo różne.
To okropne. Wykonuje niepotrzebną pracę bez uzasadnionego powodu. Nie działa w przypadku dowolnych plików. Kopia nie jest identyczna bajtowo, jeśli dane wejściowe mają nietypowe zakończenia linii w systemach takich jak Windows. Jak myślisz, dlaczego może to być łatwiejsze do zrozumienia niż wywołanie funkcji kopiowania wshutil ? Nawet przy ignorowaniu shutilprosta blokowa pętla odczytu / zapisu (wykorzystująca niebuforowane We / Wy) jest prosta, byłaby wydajna i miałaby znacznie większy sens niż to, a zatem z pewnością jest łatwiejsza do nauczenia i zrozumienia.
maxschlepzig
11
from subprocess import call
call("cp -p <file> <file>", shell=True)
A potem ktoś używa kodu (przypadkowo lub celowo) na dużym pliku… Korzystanie z funkcji z shutilobsługi wszystkich specjalnych przypadków dla ciebie i daje ci spokój.
Marcel Waldvogel
4
przynajmniej nie powtarza tych samych rozwiązań w kółko.
Pomysł jest fajny, a kod jest piękny, ale odpowiednia funkcja copy () może robić więcej rzeczy, takich jak kopiowanie atrybutów (bit + x) lub na przykład usuwanie już skopiowanych bajtów w przypadku znalezienia stanu pełnego dysku .
Raúl Salinas-Monteagudo
1
Wszystkie odpowiedzi wymagają wyjaśnienia, nawet jeśli jest to jedno zdanie. Żadne wyjaśnienie nie stanowi złego precedensu i nie jest pomocne w zrozumieniu programu. Co się stanie, jeśli pojawi się pełny Python Noob i zobaczy to, będzie chciał go użyć, ale nie może, ponieważ go nie rozumie? Chcesz być pomocny dla wszystkich w swoich odpowiedziach.
connectyourcharger
1
Czy nie brakuje tych .close()wszystkich open(...)?
luckydonald
Nie ma potrzeby .close (), ponieważ NIGDY NIE PRZECHOWYWAMY obiektu wskaźnika pliku (ani dla pliku src, ani dla pliku docelowego).
Odpowiedzi:
shutil
ma wiele metod, których możesz użyć. Jednym z nich jest:Jeśli korzystasz z
os.path
operacji, użyjcopy
raczej niżcopyfile
.copyfile
będzie akceptować tylko ciągi .źródło
~
, ale może radzić sobie ze ścieżkami względnymiźródło
copy2(src,dst)
jest często bardziej przydatny niżcopyfile(src,dst)
dlatego, że:dst
się do katalogu (zamiast pełnej nazwy pliku docelowego), w którym to przypadku basename odsrc
służy do tworzenia nowego pliku;Oto krótki przykład:
źródło
copyfile
jest znacznie szybszy niżcopy2
shutil.copy2('/dir/file.ext', '/new/dir/')
(z ukośnikiem za ścieżką docelową) usunie dwuznaczność, czy skopiować do nowego pliku o nazwie „katalog”, czy umieścić plik w katalogu o tej nazwie?/new/dir
istnieje katalog, patrz komentarz @ MatthewAlpert./new/dir/
nie istnieje, Python rzuci anIsADirectoryError
, w przeciwnym razie kopiuje plik do/new/dir/
oryginalnej nazwy.Możesz użyć jednej z funkcji kopiowania z
shutil
pakietu:Przykład:
źródło
W Pythonie możesz kopiować pliki za pomocą
shutil
modułos
modułsubprocess
moduł1) Kopiowanie plików za pomocą
shutil
modułushutil.copyfile
podpisshutil.copy
podpisshutil.copy2
podpisshutil.copyfileobj
podpis2) Kopiowanie plików za pomocą
os
modułuos.popen
podpisos.system
podpis3) Kopiowanie plików za pomocą
subprocess
modułusubprocess.call
podpissubprocess.check_output
podpisźródło
['copy', sourcefile, destfile]
składni tam, gdzie to możliwe, szczególnie jeśli parametry pochodzą z danych wprowadzonych przez użytkownika.os.popen
jest przez pewien czas przestarzałe. icheck_output
nie zwraca statusu, ale wyjście (które jest puste w przypadkucopy/cp
)Kopiowanie pliku jest stosunkowo prostą operacją, jak pokazano w poniższych przykładach, ale zamiast tego powinieneś użyć do tego modułu shutil stdlib .
Jeśli chcesz skopiować według nazwy pliku, możesz zrobić coś takiego:
źródło
shutil.copyfileobj
. Ponadto nie musisztry, finally
zajmować się zamykaniem plików po wyjątkach. Powiedziałbym jednak, że twoja funkcja nie powinna w ogóle odpowiadać za otwieranie i zamykanie plików. Powinno to przebiegać w funkcji otoki, np. Jakshutil.copyfile
otaczashutil.copyfileobj
.dest
ma być zapisywalny:open(dest, 'wb')
Użyj modułu Shutil .
Skopiuj zawartość pliku o nazwie src do pliku o nazwie dst. Lokalizacja docelowa musi być zapisywalna; w przeciwnym razie zostanie zgłoszony wyjątek IOError. Jeśli dst już istnieje, zostanie zastąpione. Za pomocą tej funkcji nie można kopiować plików specjalnych, takich jak urządzenia znakowe lub blokowe oraz potoki. src i dst to nazwy ścieżek podane jako ciągi znaków.
Spójrz na system plików dla wszystkich funkcji obsługi plików i katalogów dostępnych w standardowych modułach Python.
źródło
Przykład skopiowania katalogu i pliku - z Tima Golden'a w Pythonie:
http://timgolden.me.uk/python/win32_how_do_i/copy-a-file.html
źródło
Po pierwsze, stworzyłem wyczerpujący zestaw metod shutil dla twojego odniesienia.
Po drugie, wyjaśnij metody kopiowania w przykładach:
Rekurencyjnie skopiuj całe drzewo katalogów zrootowane na src, zwracając katalog docelowy
źródło
W przypadku małych plików i korzystania tylko z wbudowanych Pythona można użyć następującego jednowierszowego:
Jak wspomniano w komentarzach @maxschlepzig, nie jest to optymalny sposób dla aplikacji, w których plik jest zbyt duży lub gdy pamięć jest krytyczna, dlatego należy preferować odpowiedź Swati .
źródło
.read()
i.write()
są buforowane domyślnie (przynajmniej dla CPython).open()
buforuje IO, domyślnie nie pomaga tutaj, ponieważread()
jest określony jako: „Jeśli n jest ujemne lub pominięte, czytaj do EOF”. Oznacza to, żeread()
zwraca całą zawartość pliku jako ciąg.Możesz użyć
os.system('cp nameoffilegeneratedbyprogram /otherdirectory/')
lub jak to zrobiłem
gdzie
rawfile
jest nazwa, którą wygenerowałem w programie.Jest to rozwiązanie tylko dla systemu Linux
źródło
shutil
nie jest dostępny -subprocess.run()
(bezshell=True
!) Jest lepszą alternatywą dlaos.system()
.subprocess.run()
jak sugeruje @maxschlepzig, to duży krok naprzód w przypadku wywoływania programów zewnętrznych. Jednak w celu zapewnienia elastyczności i bezpieczeństwa użyj['cp', rawfile, 'rawdata.dat']
formularza przekazania wiersza polecenia. (Jednak w przypadku kopiowaniashutil
zaleca się , aby znajomi zamiast wywoływać program zewnętrzny).W przypadku dużych plików zrobiłem to, czytając plik linia po linii i czytając każdą linię w tablicy. Następnie, gdy tablica osiągnie określony rozmiar, dołącz ją do nowego pliku.
źródło
for l in open('file.txt','r'): output.write(l)
powinien znaleźć pracę; po prostu skonfiguruj bufor strumienia wyjściowego do swoich potrzeb. lub możesz przejść przez bajty, zapętlając próbę,output.write(read(n)); output.flush()
gdzien
jest liczba bajtów, którą chcesz zapisać na raz. oba z nich również nie mają warunku, aby sprawdzić, która premia.shutil
? Nawet przy ignorowaniushutil
prosta blokowa pętla odczytu / zapisu (wykorzystująca niebuforowane We / Wy) jest prosta, byłaby wydajna i miałaby znacznie większy sens niż to, a zatem z pewnością jest łatwiejsza do nauczenia i zrozumienia.źródło
call
jest niepewne. Proszę odnieść się do tego podproces docu na ten temat.Począwszy od języka Python 3.5 , możesz wykonywać następujące czynności w przypadku małych plików (tj. Plików tekstowych, małych plików JPEG):
write_bytes
nadpisze wszystko, co było w miejscu docelowymźródło
shutil
obsługi wszystkich specjalnych przypadków dla ciebie i daje ci spokój.Otwórz plik źródłowy w trybie odczytu i zapisz do pliku docelowego w trybie zapisu.
źródło
.close()
wszystkichopen(...)
?Python zapewnia wbudowane funkcje do łatwego kopiowania plików za pomocą narzędzi powłoki systemu operacyjnego.
Poniższe polecenie służy do kopiowania pliku
Poniższe polecenie służy do kopiowania pliku z informacjami MetaData
źródło
copy
Następnie należy uruchomić,copystat
aby zachować metadane pliku. W Python 3.3+copystat
kopiuje także rozszerzone atrybuty.