Как скопировать файл в Python?
Я не смог найти ничего в разделе os
.
Как скопировать файл в Python?
Я не смог найти ничего в разделе os
.
shutil
имеет много методов, которые вы можете использовать. Один из них:
from shutil import copyfile
copyfile(src, dst)
# 2nd option
copy(src, dst) # dst can be a folder; use copy2() to preserve timestamp
src
в файл с именем dst
. И src
, и dst
должны быть полными именами файлов, включая путь. IOError
. dst
уже существует, он будет заменен. copy
, src
и dst
- имена путей, заданные как str
s. Другой метод shutil
, на который стоит обратить внимание: shutil.copy2()
. Он похож, но сохраняет больше метаданных (например, отметок времени).
Если вы используете операции os.path
, используйте copy
, а не copyfile
. copyfile
принимает только строки.
shutil.copy(src, dst, *, follow_symlinks=True)
Ваш ответ может быть улучшен с помощью дополнительной вспомогательной информации. Пожалуйста, отредактируйте, чтобы добавить дополнительные сведения, такие как цитаты или документация, чтобы другие могли подтвердить правильность вашего ответа. Дополнительную информацию о том, как писать хорошие ответы, можно найти в справочном центре.
Это уже упоминалось в других ответах. Отвечая на старые вопросы, на которые уже есть ответы, убедитесь, что вы предоставили либо новое решение, либо значительно лучшее объяснение, чем существующие ответы.
shutil
предлагает некоторые высокоуровневые операции над files
. Он поддерживает файлы copying
и removal
.
Варианты использования см. в таблице ниже.
Функция | Использовать Файловый объект |
Сохранить Метаданные |
Сохранить Разрешения |
Поддерживает Адресат каталога |
---|---|---|---|---|
shutil.copyfileobj | ✔ | ⅹ | ⅹ | ⅹ |
shutil.copyfile | ⅹ | ⅹ | ⅹ | ⅹ |
shutil.copy2 | ⅹ | ✔ | ✔ | ✔ |
shutil.copy | ⅹ | ⅹ | ✔ | ✔ |
На случай, если вы зашли так далеко. Ответ заключается в том, что вам нужен полный путь и имя файла
import os
shutil.copy(os.path.join(old_dir, file), os.path.join(new_dir, file))
Подобно принятому ответу, следующий блок кода может пригодиться, если вы также хотите создать любые (несуществующие) папки на пути к месту назначения.
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):
перед этим блоком кода.
Вот простой способ сделать это без какого-либо модуля. Он похож на и этот ответ, но имеет преимущество также в том, что он работает, если это большой файл, который не помещается в ОЗУ:
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
для этого, если необходимо.
Python предоставляет встроенные функции для простого копирования файлов с помощью утилит оболочки операционной системы.
Следующая команда используется для копирования файла
shutil.copy(src,dst)
Следующая команда используется для копирования файла с метаданными
shutil.copystat(src,dst)
Вы должны запустить copy
, затем copystat
, чтобы сохранить метаданные файла. В Python 3.3+ copystat
также копирует расширенные атрибуты.
Начиная с 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
обрабатывает все особые случаи за вас и дает вам душевное спокойствие.
по крайней мере, он не повторяет одни и те же решения снова и снова.
open(destination, 'wb').write(open(source, 'rb').read())
Открыть исходный файл в режиме чтения и записать в целевой файл в режиме записи.
Идея хороша, и код красив, но правильная функция copy () может делать больше вещей, таких как копирование атрибутов (+ x бит) или, например, удаление уже скопированных байтов в случае обнаружения условия переполнения диска. .
Все ответы требуют объяснения, даже если это одно предложение. Никакие объяснения не создают плохой прецедент и не помогают понять программу. Что, если придет полный Python-нуб и увидит это, захочет использовать, но не сможет, потому что не понимает? Вы хотите быть полезным для всех в своих ответах.
Разве здесь не хватает .close()
на всех этих open(...)
?
Нет необходимости в .close (), поскольку мы НЕ СОХРАНЯЕМ объект указателя файла нигде (ни для файла src, ни для файла назначения).
Тот же неоптимальный подход к потере памяти, что и ответ yellow01.
В Python вы можете копировать файлы, используя
shutil
модуль os
модуль subprocess
модуль import os
import shutil
import subprocess
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)
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')
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]
везде, где это возможно, особенно если параметры вводятся пользователем.
Почему вы перечисляете так много плохих альтернатив функциям копирования shutil?
shutil встроен, нет необходимости предоставлять непереносимые альтернативы. На самом деле ответ можно улучшить, удалив системные решения, и после этого удаления этот ответ будет просто копией существующих ответов / копией документации.
os.popen
временно устарел. и check_output
не возвращает статус, а вывод (который пуст в случае copy/cp
)
shutil на самом деле не копирует файлы. Вверху документов есть большое жирное предупреждение. "это означает, что теряются владелец файла и группа, а также списки управления доступом. В Mac OS вилка ресурсов и другие метаданные не используются. Это означает, что ресурсы будут потеряны, а тип файла и коды создателя будут неправильными. В Windows владельцы файлов, списки управления доступом и альтернативные потоки данных не копируются ».
Во-первых, я сделал для вас исчерпывающий перечень методов 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',]
}
Во-вторых, объясните методы копирования в примерах:
shutil.copyfileobj(fsrc, fdst[, length])
манипулировать открытыми объектами
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)
shutil.copyfile(src, dst, *, follow_symlinks=True)
Скопируйте и переименуйте
In [9]: shutil.copyfile(src, dst)
IsADirectoryError: [Errno 21] Is a directory: ~/desktop'
#so dst should be a filename instead of a directory name
shutil.copy()
Копировать без сохранения метаданных
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
shutil.copy2()
Копировать с сохранением метаданных
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
shutil.copytree()
Рекурсивно копировать все дерево каталогов с корнем в src, возвращая целевой каталог
Для небольших файлов и использования только встроенных модулей Python можно использовать следующий однострочный файл:
with open(source, 'rb') as src, open(dest, 'wb') as dst: dst.write(src.read())
Как @maxschlepzig упомянул в комментариях ниже, это не оптимальный способ для приложений, где файл слишком велик или когда память критична, поэтому следует отдавать предпочтение ответу Свати.
Вы можете использовать одну из функций копирования из 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 Я просто использовал vim в качестве блокнота, скопировал использованные символы Unicode из таблицы википедии и скопировал результат в редактор coderhelper для окончательной доработки.
ХОРОШО. YMMV, но я думаю, что косметические изменения и подобные мелкие улучшения лучше вносить в существующие ответы, а не дублировать их.
Используйте subprocess.call
, чтобы скопировать файл
from subprocess import call
call("cp -p <file> <file>", shell=True)
Это зависит от платформы, поэтому я бы не стал его использовать.
Такой call
небезопасен. Пожалуйста, обратитесь к документу подпроцесса об этом.
это не переносимо и не нужно, так как вы можете просто использовать shutil.
Хм, а почему тогда Python?
Возможно, обнаружите операционную систему перед запуском (будь то DOS или Unix, потому что они наиболее часто используются)
Для больших файлов я прочитал файл построчно и прочитал каждую строку в массив. Затем, когда массив достигнет определенного размера, добавьте его в новый файл.
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 Чтобы добавить к этому вопросу год спустя, writelines()
показал немного лучшую производительность по сравнению с write()
, поскольку мы не тратим время на постоянное открытие нового файлового потока, а вместо этого записываем новые строки как один большой поток байтов.
глядя на источник - Writelines вызывает write, hg.python.org/cpython/file/c6880edaf6f3/Modules/_io/bytesio.c. Кроме того, файловый поток уже открыт, поэтому записи не нужно будет открывать его каждый раз заново.
Это ужасно. Он выполняет ненужную работу без уважительной причины. Это не работает для произвольных файлов. Копия не идентична байтам, если входные данные имеют необычные окончания строк в таких системах, как Windows. Как вы думаете, почему это проще понять, чем вызов функции копирования в shutil
? Даже при игнорировании shutil
простой цикл чтения / записи блока (с использованием небуферизованного ввода-вывода) будет прямым, будет эффективным и будет иметь гораздо больше смысла, чем этот, и, следовательно, его, безусловно, легче научить и понять.
Это также увеличивает накладные расходы на декодирование / кодирование и не работает с двоичными данными. Просто используйте shutil.copyfile()
, который в 3.8 был дополнительно улучшен, чтобы использовать встроенную поддержку ОС для быстрого копирования файлов. Это легко займет меньше половины времени от того, что займет этот ответ.
Функция | Копирует метаданные |
Копирует разрешения |
Использует файловый объект | Назначением может быть каталог |
---|---|---|---|---|
shutil.copy | Нет | Да | Нет | Да |
shutil.copyfile | Нет | Нет | Нет | Нет |
shutil.copy2 | Да | Да | Нет | Да |
shutil.copyfileobj | Нет | Нет | Да | Нет |
Вы можете использовать os.system('cp nameoffilegeneratedbyprogram /otherdirectory/')
или, как я,
os.system('cp '+ rawfile + ' rawdata.dat')
, где rawfile
- это имя, которое я создал внутри программы.
Это решение только для Linux
это не переносимо и не нужно, так как вы можете просто использовать shutil.
Даже когда shutil
недоступен - subprocess.run()
(без shell=True
!) Является лучшей альтернативой os.system()
.
shutil более портативный
subprocess.run()
, предложенный @maxschlepzig, является большим шагом вперед при вызове внешних программ. Однако для гибкости и безопасности используйте форму ['cp', rawfile, 'rawdata.dat']
передачи командной строки. (Однако для копирования рекомендуется shutil
и друзьям вместо вызова внешней программы.)
попробуйте это с именами файлов с пробелами.
Пример копирования каталога и файла - из материалов Тима Голдена о 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"
Копирование файла - относительно простая операция, как показано в примерах ниже, но вместо этого вы должны использовать для этого модуль 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. Тем не менее, я оставляю эту функцию здесь в качестве примера.
copy2(src,dst)
часто более полезен, чем copyfile(src,dst)
, потому что:
dst
быть каталогом (вместо полного целевого имени файла), и в этом случае базовое имя из src
используется для создания нового файла; Вот краткий пример:
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
Используйте модуль shutil.
copyfile(src, dst)
Скопируйте содержимое файла с именем src в файл с именем dst. Место назначения должно быть доступно для записи; в противном случае возникнет исключение IOError. Если dst уже существует, он будет заменен. Специальные файлы, такие как символьные или блочные устройства и каналы, не могут быть скопированы с помощью этой функции. src и dst - имена путей, заданные в виде строк.
Взгляните на filesys для всех функций обработки файлов и каталогов, доступных в стандартных модулях Python.
В чем разница между копией и копией файла?
в копии (src, dst) dst может быть каталогом.
Обратите внимание, что не все метаданные будут скопированы, в зависимости от вашей платформы.
Обратите внимание, что это не атомарная операция. Будьте осторожны, используя его в многопоточном приложении.
Обратите внимание, что он не может обрабатывать сокращения вроде
~
, но может работать с относительными путями.@Owen Действительно может, но каталог уже должен существовать. Кстати, пока целевой каталог уже существует,
dst
может заканчиваться или не заканчиваться косой чертой в конце, это не имеет значения.Чтобы создать все целевые каталоги промежуточного уровня, вы можете использовать os.makedirs () перед копированием, подробности здесь coderhelper.com/questions/12842997/…
shutil на самом деле не копирует файлы. Вверху документов есть большое жирное предупреждение. "это означает, что теряются владелец файла и группа, а также списки управления доступом. В Mac OS вилка ресурсов и другие метаданные не используются. Это означает, что ресурсы будут потеряны, а тип файла и коды создателя будут неправильными. В Windows владельцы файлов, списки управления доступом и альтернативные потоки данных не копируются ».
В Python 3.8 это значительно увеличило скорость (примерно на 50% быстрее, в зависимости от ОС).
copy или copyfile, похоже, не заменяют файл, если dst уже существует 🤔. Получение SameFileError
Если вы хотите, чтобы изображения были ясны: ao.gl/how-to-copy-a-file-in-python