Как можно скопировать файл?

Как скопировать файл в Python?

Я ничего не нашел в разделе os.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2 854
0
2 319 455
19
Перейти к ответу Данный вопрос помечен как решенный

Ответы 19

Ответ принят как подходящий

shutil имеет много методов, которые вы можете использовать. Один из них:

from shutil import copyfile
copyfile(src, dst)
  • Скопируйте содержимое файла src в файл dst.
  • Место назначения должно быть доступно для записи; в противном случае возникнет исключение IOError.
  • Если dst уже существует, он будет заменен.
  • Специальные файлы, такие как символьные или блочные устройства и каналы, не могут быть скопированы с помощью этой функции.
  • Для copy, src и dst - это пути, заданные как str.

Еще один метод shutil - shutil.copy2(). Он похож, но сохраняет больше метаданных (например, отметок времени).

Если вы используете операции os.path, используйте copy, а не copyfile. copyfile принимает только строки.

В чем разница между копией и копией файла?

Matt 23.09.2008 23:47

в копии (src, dst) dst может быть каталогом.

Owen 23.09.2008 23:51

Обратите внимание, что не все метаданные будут скопированы, в зависимости от вашей платформы.

Kevin Horn 20.10.2009 00:50

Обратите внимание, что это не атомарная операция. Будьте осторожны, используя его в многопоточном приложении.

waterbyte 22.10.2018 14:53

Обратите внимание, что он не может обрабатывать сокращения, такие как ~, но может работать с относительными путями.

zwep 27.11.2018 13:00

@Owen Действительно может, но каталог уже должен существовать. Кстати, пока целевой каталог уже существует, dst может заканчиваться или не заканчиваться косой чертой в конце, это не имеет значения.

Jack M 25.12.2018 17:34

Чтобы создать все целевые каталоги промежуточного уровня, вы можете использовать os.makedirs () перед копированием, подробности здесь stackoverflow.com/questions/12842997/…

Alexei Martianov 03.01.2019 08:37

shutil на самом деле не копирует файлы. Есть большое жирное предупреждение прямо в верхней части документации. "это означает, что теряются владелец файла и группа, а также списки управления доступом. В Mac OS вилка ресурсов и другие метаданные не используются. Это означает, что ресурсы будут потеряны, а тип файла и коды создателя будут неправильными. В Windows владельцы файлов, списки управления доступом и альтернативные потоки данных не копируются ».

gman 25.11.2019 06:04

В Python 3.8 это значительно увеличило скорость (примерно на 50% быстрее, в зависимости от ОС).

Martijn Pieters 20.03.2020 12:17

copy или copyfile, похоже, не заменяют файл, если dst уже существует ?. Получение SameFileError

Debvrat Varshney 03.08.2020 01:35

Если вы хотите, чтобы несколько изображений помогли с ясностью: ao.gl/how-to-copy-a-file-in-python

AO_ 18.08.2020 09:49

Используйте модуль shutil.

copyfile(src, dst)

Скопируйте содержимое файла с именем src в файл с именем dst. Место назначения должно быть доступно для записи; в противном случае возникнет исключение IOError. Если dst уже существует, он будет заменен. Специальные файлы, такие как символьные или блочные устройства и каналы, не могут быть скопированы с помощью этой функции. src и dst - имена путей, заданные в виде строк.

Взгляните на filesys для всех функций обработки файлов и каталогов, доступных в стандартных модулях Python.

shutil на самом деле не копирует файлы. Есть большое жирное предупреждение прямо в верхней части документации. "это означает, что теряются владелец файла и группа, а также списки управления доступом. В Mac OS вилка ресурсов и другие метаданные не используются. Это означает, что ресурсы будут потеряны, а тип файла и коды создателя будут неправильными. В Windows владельцы файлов, списки управления доступом и альтернативные потоки данных не копируются ».

gman 25.11.2019 06:03

copy2(src,dst) часто более полезен, чем copyfile(src,dst), потому что:

  • он позволяет dst быть каталог (вместо полного целевого имени файла), и в этом случае базовое имяsrc используется для создания нового файла;
  • он сохраняет исходную информацию о модификации и доступе (mtime и atime) в метаданных файла (однако это связано с небольшими накладными расходами).

Вот небольшой пример:

import shutil
shutil.copy2('/src/dir/file.ext', '/dst/dir/newname.ext') # complete target filename given
shutil.copy2('/src/file.ext', '/dst/dir') # target filename is /dst/dir/file.ext

Я пытаюсь случайным образом скопировать 100k файлов из 1 миллиона файлов. copyfile значительно быстрее copy2

Vijay 07.05.2014 12:31

Правильно ли я предполагаю, что shutil.copy2('/dir/file.ext', '/new/dir/') (с косой чертой после целевого пути) устранит двусмысленность относительно того, следует ли копировать в новый файл с именем «dir» или поместить файл в каталог с этим именем?

Zak 19.08.2015 21:56

@Vijay Я считаю, что эти накладные расходы связаны с копированием метаданных.

Jonathan H 13.03.2017 20:57

@Zak Нет двусмысленности, если /new/dir - существующий каталог, см. Комментарий @ MatthewAlpert.

Jonathan H 13.03.2017 21:14

@Zak Вы правы, добавление косой черты в конце устраняет двусмысленность. Если /new/dir/ не существует, Python выдаст IsADirectoryError, в противном случае он копирует файл в /new/dir/ под исходным именем.

martonbognar 07.06.2018 15:00

shutil на самом деле не копирует файлы. Есть большое жирное предупреждение прямо в верхней части документации. "это означает, что теряются владелец файла и группа, а также списки управления доступом. В Mac OS вилка ресурсов и другие метаданные не используются. Это означает, что ресурсы будут потеряны, а тип файла и коды создателя будут неправильными. В Windows владельцы файлов, списки управления доступом и альтернативные потоки данных не копируются ».

gman 25.11.2019 06:04

Копирование файла - относительно простая операция, как показано в примерах ниже, но вместо этого вы должны использовать для этого модуль 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.
    """
    while True:
        copy_buffer = source.read(buffer_size)
        if not copy_buffer:
            break
        dest.write(copy_buffer)

Если вы хотите скопировать по имени файла, вы можете сделать что-то вроде этого:

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)

Некоторое время назад я заметил, что модуль называется shutil (единственное число), а не shutils (множественное число), и действительно, это является в Python 2.3. Тем не менее, я оставляю эту функцию здесь в качестве примера.

pi. 31.03.2009 19:20

Копирование содержание файла - простая операция. Копировать файл с его метаданными совсем непросто, тем более, если вы хотите быть кроссплатформенным.

LaC 16.01.2012 22:01

Истинный. Глядя на документацию shutil, функция copyfile также не копирует метаданные.

pi. 17.01.2012 19:08

Кстати, если вы хотите скопировать содержимое между двумя файловыми объектами, есть shutil.copyfileobj(fsrc, fdst)

Haroldo_OK 19.08.2014 17:14

Да, я не уверен, почему бы вам просто не скопировать исходный код shutil.copyfileobj. Кроме того, у вас нет try, finally для обработки закрытия файлов после исключений. Я бы сказал, однако, что ваша функция вообще не должна отвечать за открытие и закрытие файлов. Это должно быть в функции-оболочке, например, как shutil.copyfile оборачивает shutil.copyfileobj.

ErlVolton 28.10.2014 21:48

В приведенном выше коде должен быть указан dest для записи: open(dest, 'wb')

user1016274 28.05.2015 17:56

@pi., для копирования метаданных у нас есть shutil.copy() и shutil.copy2(). stackoverflow.com/a/44996087/2445204

Marcel Waldvogel 29.04.2019 06:31

Пример копирования каталогов и файлов - из материалов Тима Голдена о Python:

http://timgolden.me.uk/python/win32_how_do_i/copy-a-file.html

import os
import shutil
import tempfile

filename1 = tempfile.mktemp (".txt")
open (filename1, "w").close ()
filename2 = filename1 + ".copy"
print filename1, "=>", filename2

shutil.copy (filename1, filename2)

if os.path.isfile (filename2): print "Success"

dirname1 = tempfile.mktemp (".dir")
os.mkdir (dirname1)
dirname2 = dirname1 + ".copy"
print dirname1, "=>", dirname2

shutil.copytree (dirname1, dirname2)

if os.path.isdir (dirname2): print "Success"

Вы можете использовать os.system('cp nameoffilegeneratedbyprogram /otherdirectory/')

или как я это сделал,

os.system('cp '+ rawfile + ' rawdata.dat')

где rawfile - это имя, которое я создал внутри программы.

Это решение только для Linux

это не переносимо и не нужно, так как вы можете просто использовать shutil.

Corey Goldberg 12.06.2017 17:05

Даже когда shutil недоступен - subprocess.run() (без shell=True!) Является лучшей альтернативой os.system().

maxschlepzig 09.07.2017 14:52

shutil более портативный

Hiadore 12.03.2019 12:07

subprocess.run(), предложенный @maxschlepzig, - большой шаг вперед при вызове внешних программ. Однако для гибкости и безопасности используйте форму ['cp', rawfile, 'rawdata.dat'] для передачи командной строки. (Однако для копирования рекомендуется использовать shutil и его друзья, а не вызывать внешнюю программу.)

Marcel Waldvogel 29.04.2019 06:09

попробуйте это с именами файлов с пробелами.

Jean-François Fabre 29.04.2019 20:21
ФункцияКопирует
метаданные
Копии разрешений
Использует файловый объектDestination
может быть каталогом
shutil.copyНетдаНетда
shutil.copyfileНетНетНетНет
shutil.copy2дадаНетда
shutil.copyfileobjНетНетдаНет

предоставляет ли shutil копию с режимом добавления в место назначения вместо перезаписи?

Syed Mohammed Mehdi 20.06.2020 23:11

Что означает «Может использовать буфер»?

lucidbrot 14.08.2020 13:38

@lucidbrot - Если проверять это - The integer length, if given, is the buffer size. In particular, a negative length value means to copy the data without looping over the source data in chunks; by default the data is read in chunks to avoid uncontrolled memory consumption.

jezrael 14.08.2020 13:44

Это довольно неточно, извините. shutil будет использовать копирование данных по частям в любом случае. Например. copy2 вызывает copyfile(), который, в свою очередь, вызывает copyfileobj(), который выполняет копирование по частям. Единственное отличие: copyfileobj() позволяет явно указать размер буфера (при желании), другие функции просто используют размер буфера по умолчанию shutil и не предлагают возможности его настройки. Таким образом, столбец «можно использовать буфер» не имеет никакого смысла. Буфер используется все время. Если для -1 указан copyfileobj, он будет такого же размера, как и сам файл.

Regis May 13.12.2020 10:17

@RegisMay - Спасибо за комментарий. Так что лучше поменять can use buffer на can specify buffer?

jezrael 14.12.2020 09:30

@jezrael: Нет. Если вы хотите что-то указать, вам нужно будет назвать это can specify buffer size. Но в этом нет особого смысла: размер буфера очень разумный, поэтому нет необходимости в каких-либо изменениях. Обычным пользователям просто не нужно менять размер буфера. Если это будет проблемой для вас, чтобы вы подумали об изменении размера буфера, вы, скорее всего, все равно решите отказаться от python и flask для своего проекта, поскольку изменение размера буфера не поможет вам в достаточной степени, если у вас есть какие-либо проблемы с производительностью. . Моя рекомендация: удалите этот столбец ;-)

Regis May 14.12.2020 11:34

@jezrael: Ненавижу это говорить, но с модулями Python всегда полезно взглянуть на код. Так быть не должно, поскольку должно быть достаточно хорошо написанной документации, чтобы узнать о модуле без, глядя на код. Но с модулями Python всегда полезно смотреть на код.

Regis May 14.12.2020 11:39

@RegisMay - я проверяю аналогичный ответ ниже, и кажется, что это было решено путем изменения can use buffer на accepts file obj. Думаю, в этом главное отличие обоих ответов. Поэтому, на мой взгляд, вместо удаления лучше переименовать его.

jezrael 14.12.2020 11:50

@jezrael: Делай как хочешь, но я думаю, что лучше удалить. Для обычных пользователей Python НИКОГДА НЕ НУЖНО изменять размер буфера, если он / она хочет скопировать файлы. Скорее всего, авторы shutils чувствовали то же самое: вероятно, именно по этой причине: а) вы не можете указать размер буфера во время копирования; б) и нет никакого способа изменить его в целом. Так что эта информация скорее вводит в заблуждение, чем помогает. Обычно вы НЕ захотите читать полные данные файла в память, если собираетесь копировать файлы.

Regis May 14.12.2020 12:39

Для больших файлов я прочитал файл построчно и прочитал каждую строку в массив. Затем, когда массив достигнет определенного размера, добавьте его в новый файл.

for line in open("file.txt", "r"):
    list.append(line)
    if len(list) == 1000000: 
        output.writelines(list)
        del list[:]

это кажется немного избыточным, поскольку писатель должен обрабатывать буферизацию. for l in open('file.txt','r'): output.write(l) должен работать найти; просто настройте буфер выходного потока в соответствии с вашими потребностями. или вы можете переходить по байтам, повторяя попытку с output.write(read(n)); output.flush(), где n - это количество байтов, которое вы хотите записать за раз. у обоих из них также нет условия для проверки того, что является бонусом.

owns 12.06.2015 20:30

Да, но я подумал, что, возможно, это будет легче понять, потому что он копирует целые строки, а не их части (на случай, если мы не знаем, сколько байтов в каждой строке).

ytpillai 13.06.2015 21:42

Совершенно верно. Кодирование для обучения и кодирование для повышения эффективности очень разные.

owns 15.06.2015 20:47

@owns Чтобы добавить к этому вопросу год спустя, writelines() показал немного лучшую производительность по сравнению с write(), поскольку мы не тратим время на постоянное открытие нового файлового потока, а вместо этого записываем новые строки как один большой поток байтов.

ytpillai 30.11.2016 06:33

глядя на источник - Writelines вызывает write, hg.python.org/cpython/file/c6880edaf6f3/Modules/_io/bytesio.‌ c. Кроме того, файловый поток уже открыт, поэтому записи не нужно будет открывать его каждый раз заново.

owns 03.05.2017 03:24

Это ужасно. Он выполняет ненужную работу без уважительной причины. Это не работает для произвольных файлов. Копия не идентична байтам, если входные данные имеют необычные окончания строк в таких системах, как Windows. Как вы думаете, почему это проще понять, чем вызов функции копирования в shutil? Даже при игнорировании shutil простой цикл блочного чтения / записи (с использованием небуферизованного ввода-вывода) будет прямым, будет эффективным и будет иметь гораздо больше смысла, чем этот, и, следовательно, его, безусловно, легче научить и понять.

maxschlepzig 29.04.2019 22:04

Это также увеличивает накладные расходы на декодирование / кодирование и не работает с двоичными данными. Просто используйте shutil.copyfile(), который в 3.8 был дополнительно улучшен, чтобы использовать встроенную поддержку ОС для быстрого копирования файлов. Это легко займет меньше половины времени от того, что займет этот ответ.

Martijn Pieters 20.03.2020 12:13

from subprocess import call
call("cp -p <file> <file>", shell=True)

Это зависит от платформы, поэтому я бы не стал его использовать.

Kevin Meier 13.09.2016 13:02

Такой call небезопасен. Пожалуйста, обратитесь к документу подпроцесса об этом.

buhtz says get vaccinated 02.04.2017 10:57

это не переносимо и не нужно, так как вы можете просто использовать shutil.

Corey Goldberg 12.06.2017 17:05

Хм, а почему тогда Python?

Baris Demiray 07.07.2017 12:29

Возможно, обнаружите операционную систему перед запуском (будь то DOS или Unix, потому что они наиболее часто используются)

MilkyWay90 09.11.2018 18:51

Вы можете использовать одну из функций копирования из пакета shutil:

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Function              preserves     supports          accepts     copies other
                      permissions   directory dest.   file obj    metadata  
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
shutil.copy              ✔             ✔                 ☐           ☐
shutil.copy2             ✔             ✔                 ☐           ✔
shutil.copyfile          ☐             ☐                 ☐           ☐
shutil.copyfileobj       ☐             ☐                 ✔           ☐
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Пример:

import shutil
shutil.copy('/etc/hostname', '/var/tmp/testhostname')

Просто любопытно, как вы создали эту таблицу?

lightalchemist 02.12.2018 10:40

@lightalchemist Я просто использовал vim в качестве блокнота, скопировал использованные символы Unicode из таблицы википедии и скопировал результат в редактор stackoverflow для окончательной полировки.

maxschlepzig 02.12.2018 20:02

Чем это отличается от другого ответа двумя годами ранее? stackoverflow.com/a/30359308/674039

wim 09.11.2019 00:22

@wim, вы должны сравнить мой ответ с Версия ответа, который вы связали, 2017 г., которое было текущим, когда я опубликовал свой ответ. Основные отличия: в моем ответе используются более качественные / описательные заголовки столбцов, макет таблицы не отвлекает, он включает прямые ссылки на документацию, и я добавил столбец (т.е. «принимает файл obj»).

maxschlepzig 09.11.2019 00:58

В ПОРЯДКЕ. YMMV, но я думаю, что косметические изменения и подобные мелкие улучшения лучше вносить в существующие ответы, а не дублировать их.

wim 09.11.2019 01:04

@wim проверьте ссылку, которую я опубликовал, это было бы довольно существенным изменением существующего ответа.

maxschlepzig 09.11.2019 01:37

shutil на самом деле не копирует файлы. Есть большое жирное предупреждение прямо в верхней части документации. "это означает, что теряются владелец файла и группа, а также списки управления доступом. В Mac OS вилка ресурсов и другие метаданные не используются. Это означает, что ресурсы будут потеряны, а тип файла и коды создателя будут неправильными. В Windows владельцы файлов, списки управления доступом и альтернативные потоки данных не копируются ».

gman 25.11.2019 06:05

@gman 'shutil фактически не копирует файлы' - это очень вводящее в заблуждение утверждение - предупреждение, на которое вы ссылаетесь, касается метаданных. В зависимости от вашего варианта использования вы действительно или явно не хотите копировать определенные виды метаданных. Конечно, с обычными привилегиями пользователя информация о владельце пользователя / группы часто легко теряется из-за недостаточных привилегий! С этим ничего не может поделать функция копирования высокого уровня!

maxschlepzig 25.11.2019 23:15

Заблуждение состоит в том, что эти функции копируют файлы. Они этого не делают. Они читают файл и записывают новый. Доказательство. Попытка копирования с cp на Mac или copy на Windows. Повторите эти действия с этими функциями. Эти функции не дают одинакового результата. Данные теряются, большая часть из них - важные данные. В качестве встречного примера функция C# Copy фактически копирует файлы, по крайней мере, на Mac и Windows. Node также копирует в Windows (ошибка на Mac). Пример: controlc.com/f3e3b9f7

gman 26.11.2019 08:32

Для небольших файлов и использования только встроенных модулей Python вы можете использовать следующий однострочный файл:

with open(source, 'rb') as src, open(dest, 'wb') as dst: dst.write(src.read())

Как @maxschlepzig упомянул в комментариях ниже, это не оптимальный способ для приложений, где файл слишком велик или когда память критична, поэтому следует отдавать предпочтение ответу Свати.

Это считывает полный исходный файл в память перед его обратной записью. Таким образом, это излишне тратит память на все операции копирования файлов, кроме самых мелких.

maxschlepzig 02.10.2017 10:11

Это правда? Я думаю, что .read() и .write() по умолчанию буферизированы (по крайней мере, для CPython).

soundstripe 17.11.2017 04:39

@soundstripe, конечно это правда. Тот факт, что объект файла, возвращаемый open(), выполняет буферизованный ввод-вывод, по умолчанию вам здесь не поможет, потому что read() указан как: «Если n отрицательное или опущено, читать до EOF». Это означает, что read() возвращает полное содержимое файла в виде строки.

maxschlepzig 29.04.2019 14:00

@maxschlepzig Я понимаю вашу точку зрения и признаю, что не знал об этом. Причина, по которой я дал этот ответ, заключалась в том, что кто-то хотел сделать простую копию файла, используя только встроенные модули, без необходимости импортировать для него модуль. Конечно, оптимизация памяти не должна вызывать беспокойства, если вам нужна эта опция. В любом случае, спасибо, что прояснили это. Я обновил ответ соответственно.

fabda01 29.04.2019 21:36

Во-первых, я сделал для вас исчерпывающий перечень методов shutil.

shutil_methods =
{'copy':['shutil.copyfileobj',
          'shutil.copyfile',
          'shutil.copymode',
          'shutil.copystat',
          'shutil.copy',
          'shutil.copy2',
          'shutil.copytree',],
 'move':['shutil.rmtree',
         'shutil.move',],
 'exception': ['exception shutil.SameFileError',
                 'exception shutil.Error'],
 'others':['shutil.disk_usage',
             'shutil.chown',
             'shutil.which',
             'shutil.ignore_patterns',]
}

Во-вторых, объясните методы копирования в примерах:

  1. shutil.copyfileobj(fsrc, fdst[, length]) manipulate opened objects
In [3]: src = '~/Documents/Head+First+SQL.pdf'
In [4]: dst = '~/desktop'
In [5]: shutil.copyfileobj(src, dst)
AttributeError: 'str' object has no attribute 'read'
#copy the file object
In [7]: with open(src, 'rb') as f1,open(os.path.join(dst,'test.pdf'), 'wb') as f2:
    ...:      shutil.copyfileobj(f1, f2)
In [8]: os.stat(os.path.join(dst,'test.pdf'))
Out[8]: os.stat_result(st_mode=33188, st_ino=8598319475, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516067347, st_mtime=1516067335, st_ctime=1516067345)
  1. shutil.copyfile(src, dst, *, follow_symlinks=True) Copy and rename
In [9]: shutil.copyfile(src, dst)
IsADirectoryError: [Errno 21] Is a directory: ~/desktop'
#so dst should be a filename instead of a directory name
  1. shutil.copy() Copy without preseving the metadata
In [10]: shutil.copy(src, dst)
Out[10]: ~/desktop/Head+First+SQL.pdf'
#check their metadata
In [25]: os.stat(src)
Out[25]: os.stat_result(st_mode=33188, st_ino=597749, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516066425, st_mtime=1493698739, st_ctime=1514871215)
In [26]: os.stat(os.path.join(dst, 'Head+First+SQL.pdf'))
Out[26]: os.stat_result(st_mode=33188, st_ino=8598313736, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516066427, st_mtime=1516066425, st_ctime=1516066425)
# st_atime,st_mtime,st_ctime changed
  1. shutil.copy2() Copy with preseving the metadata
In [30]: shutil.copy2(src, dst)
Out[30]: ~/desktop/Head+First+SQL.pdf'
In [31]: os.stat(src)
Out[31]: os.stat_result(st_mode=33188, st_ino=597749, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516067055, st_mtime=1493698739, st_ctime=1514871215)
In [32]: os.stat(os.path.join(dst, 'Head+First+SQL.pdf'))
Out[32]: os.stat_result(st_mode=33188, st_ino=8598313736, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516067063, st_mtime=1493698739, st_ctime=1516067055)
# Preseved st_mtime
  1. shutil.copytree()

Рекурсивно копировать все дерево каталогов с корнем src, возвращая целевой каталог

shutil на самом деле не копирует файлы. Есть большое жирное предупреждение прямо в верхней части документации. "это означает, что теряются владелец файла и группа, а также списки управления доступом. В Mac OS вилка ресурсов и другие метаданные не используются. Это означает, что ресурсы будут потеряны, а тип файла и коды создателя будут неправильными. В Windows владельцы файлов, списки управления доступом и альтернативные потоки данных не копируются ».

gman 25.11.2019 06:03

В Python вы можете копировать файлы, используя

  • Модуль shutil
  • Модуль os
  • Модуль subprocess

import os
import shutil
import subprocess

1) Копирование файлов с помощью модуля shutil

Подпись shutil.copyfile

shutil.copyfile(src_file, dest_file, *, follow_symlinks=True)

# example    
shutil.copyfile('source.txt', 'destination.txt')

Подпись shutil.copy

shutil.copy(src_file, dest_file, *, follow_symlinks=True)

# example
shutil.copy('source.txt', 'destination.txt')

Подпись shutil.copy2

shutil.copy2(src_file, dest_file, *, follow_symlinks=True)

# example
shutil.copy2('source.txt', 'destination.txt')  

Подпись shutil.copyfileobj

shutil.copyfileobj(src_file_object, dest_file_object[, length])

# example
file_src = 'source.txt'  
f_src = open(file_src, 'rb')

file_dest = 'destination.txt'  
f_dest = open(file_dest, 'wb')

shutil.copyfileobj(f_src, f_dest)  

2) Копирование файлов с помощью модуля os

Подпись os.popen

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

Подпись os.system

os.system(command)


# In Linux/Unix
os.system('cp source.txt destination.txt')  

# In Windows
os.system('copy source.txt destination.txt')

3) Копирование файлов с помощью модуля subprocess

Подпись subprocess.call

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

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)

Использование однострочных команд является плохим стилем кодирования (гибкость, надежность и безопасность), вместо этого используйте синтаксис ['copy', sourcefile, destfile] везде, где это возможно, особенно если параметры вводятся пользователем.

Marcel Waldvogel 29.04.2019 06:03

Почему вы перечисляете так много плохих альтернатив функциям копирования shutil?

maxschlepzig 29.04.2019 14:08

shutil встроен, нет необходимости предоставлять непереносимые альтернативы. На самом деле ответ можно улучшить, удалив системные решения, и после этого удаления этот ответ будет просто копией существующих ответов / копией документации.

Jean-François Fabre 29.04.2019 20:19

os.popen на некоторое время устарел. и check_output возвращает не статус, а вывод (который пуст в случае copy/cp)

Jean-François Fabre 29.04.2019 21:12

shutil на самом деле не копирует файлы. Есть большое жирное предупреждение прямо в верхней части документации. "это означает, что теряются владелец файла и группа, а также списки управления доступом. В Mac OS вилка ресурсов и другие метаданные не используются. Это означает, что ресурсы будут потеряны, а тип файла и коды создателя будут неправильными. В Windows владельцы файлов, списки управления доступом и альтернативные потоки данных не копируются ».

gman 25.11.2019 06:03

open(destination, 'wb').write(open(source, 'rb').read())

Откройте исходный файл в режиме чтения и запишите в целевой файл в режиме записи.

Идея хороша, и код красив, но правильная функция copy () может делать больше вещей, таких как копирование атрибутов (+ x бит) или, например, удаление уже скопированных байтов в случае обнаружения условия переполнения диска. .

Raúl Salinas-Monteagudo 29.03.2019 14:06
Все answers need explanation, even if it is one sentence. No explanation sets bad precedent and is not helpful in understanding the program. What if a complete Python noob came along and saw this, wanted to use it, but couldn't because they don't understand it? You want to be helpful to all in your answers.
connectyourcharger 31.03.2019 01:19

Разве это не отсутствие .close() на всех open(...)?

luckydonald 23.04.2019 01:37

Нет необходимости в .close (), поскольку мы НЕ СОХРАНЯЕМ объект указателя файла нигде (ни для файла src, ни для файла назначения).

Sundeep471 24.04.2019 00:19

AFAIK, это не определено, когда файлы действительно закрыты, @SundeepBorra. Использование with (как в примере выше) рекомендуется и не более сложно. Использование read() для необработанного файла приводит к считыванию всего файла в память, которая может быть слишком большой. Используйте стандартную функцию, например, из shutil, чтобы вам и всем, кто участвует в коде, не нужно было беспокоиться об особых случаях. docs.python.org/3/library/io.html#io.BufferedReader

Marcel Waldvogel 29.04.2019 06:17

Тот же подход к неоптимальному расходу памяти, что и ответ yellow01.

maxschlepzig 29.04.2019 14:04

Начиная с Python 3.5, вы можете делать следующее для небольших файлов (например, текстовых файлов, маленьких jpeg):

from pathlib import Path

source = Path('../path/to/my/file.txt')
destination = Path('../path/where/i/want/to/store/it.txt')
destination.write_bytes(source.read_bytes())

write_bytes перезапишет все, что было в месте назначения

А затем кто-то использует код (случайно или целенаправленно) в большом файле ... Использование функций из shutil решает все особые случаи за вас и дает вам душевное спокойствие.

Marcel Waldvogel 29.04.2019 06:21

по крайней мере, он не повторяет одни и те же решения снова и снова.

Jean-François Fabre 29.04.2019 21:16

Python предоставляет встроенные функции для простого копирования файлов с помощью утилит оболочки операционной системы.

Следующая команда используется для копирования файла

shutil.copy(src,dst)

Следующая команда используется для копирования файла с информацией о метаданных.

shutil.copystat(src,dst)

Вы должны запустить copy, затем copystat, чтобы сохранить метаданные файла. В Python 3.3+ copystat также копирует расширенные атрибуты.

ingyhere 22.05.2020 20:25

Вот простой способ сделать это без какого-либо модуля. Он похож на этот ответ, но имеет то преимущество, что он также работает, если это большой файл, который не помещается в ОЗУ:

with open('sourcefile', 'rb') as f, open('destfile', 'wb') as g:
    while True:
        block = f.read(16*1024*1024)  # work by blocks of 16 MB
        if not block:  # end of file
            break
        g.write(block)

Поскольку мы пишем новый файл, он не сохраняет время модификации и т. д.
Затем мы можем использовать для этого os.utime, если это необходимо.

Подобно принятому ответу, следующий блок кода может пригодиться, если вы также хотите создать любые (несуществующие) папки на пути к месту назначения.

from os import path, makedirs
from shutil import copyfile
makedirs(path.dirname(path.abspath(destination_path)), exist_ok=True)
copyfile(source_path, destination_path)

Как отмечается в принятых ответах, эти строки перезапишут любой файл, который существует по пути назначения, поэтому иногда может быть полезно также добавить: if not path.exists(destination_path): перед этим блоком кода.

На случай, если вы зашли так далеко. Ответ в том, что вам нужен полный путь и имя файла.

import os

shutil.copy(os.path.join(old_dir, file), os.path.join(new_dir, file))

Другие вопросы по теме