Как переместить файл?

910

Я посмотрел на osинтерфейс Python , но не смог найти метод для перемещения файла. Как бы я сделал эквивалент $ mv ...в Python?

>>> source_files = '/PATH/TO/FOLDER/*'
>>> destination_folder = 'PATH/TO/FOLDER'
>>> # equivalent of $ mv source_files destination_folder
David542
источник
1
для тех из вас, кто знаком с командой gnu-coreutilsmv , в python shutil.moveесть один крайний случай, когда shutil.moveфункция отличается. Иди сюда для полной записи . В двух словах, Python shutil.moveбудет вызывать исключение (но gnu-coreutils mvне будет), когда вашим местом назначения является каталог, а в каталоге уже есть файл с тем же именем, что и у источника (опять же, для получения дополнительной информации см. Ссылку, приведенную в предыдущем предложении). ).
Тревор Бойд Смит
3
Как насчет os.system("mv file1 file2")?
Джон Струд

Ответы:

1341

os.rename(), shutil.move()Илиos.replace()

Все используют один и тот же синтаксис:

import os
import shutil

os.rename("path/to/current/file.foo", "path/to/new/destination/for/file.foo")
shutil.move("path/to/current/file.foo", "path/to/new/destination/for/file.foo")
os.replace("path/to/current/file.foo", "path/to/new/destination/for/file.foo")

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

Также обратите внимание, что в первых двух случаях каталог, в котором создается новый файл, уже должен существовать. В Windows файл с таким именем не должен существовать, иначе возникнет исключение, но он os.replace()будет автоматически заменять файл даже в этом случае.

Как было отмечено в комментариях к другим ответам, в большинстве случаев shutil.moveпросто звонки os.rename. Однако, если место назначения находится на диске, отличном от исходного, оно вместо этого скопирует и затем удалит исходный файл.

ig0774
источник
8
Я единственный, кто думает, что os.rename не работает для каталогов? Я цитирую: «Если dst - это каталог, OSError будет вызван».
Фабиан
33
shutil.moveработает для каталогов. Вы можете использовать относительный путь shutil.move(f.name, "tmp/")или полный путь shutil.move(f.name, "/Users/hello/tmp/"), не использовать ~ в пути, проверено в python2.7.9, Mac OS X.
whyisyoung
3
~является оболочкой и не имеет ничего общего с путями к файлам как таковым, за исключением неуместного соглашения. Если вы действительно хотите задействовать свой домашний каталог, используйте os.getenv('HOME')вместо этого, объединяя его с частями желаемого пути, если это необходимо.
amn
15
Вы всегда можете использовать os.path.expanduser()для правильного расширения ' ~' в соответствии с ос-специфическими правилами. Намного аккуратнее, так %HOME%как не всегда устанавливается на Windows.
ig0774
14
os.renameне будет обрабатывать файлы на разных устройствах. Используйте, shutil.moveесли вы не уверены, что исходный файл и файл назначения находятся на одном устройстве.
Джузеппе Скривано
244

Хотя os.rename()и shutil.move()будут переименовывать файлы, команда, которая ближе всего к команде Unix mv shutil.move(). Разница в том, что os.rename()не работает, если источник и место назначения находятся на разных дисках, shutil.move()и не заботится о том, на каком диске находятся файлы.

Джим Кальфас
источник
75
shutil.move()использует, os.rename()если место назначения находится в текущей файловой системе. В противном случае shutil.move()копирует источник в пункт назначения с помощью, shutil.copy2()а затем удаляет источник.
разрыв строки
8
Позаботьтесь о том, чтобы понять, что shutil.copy2()нельзя копировать все метаданные файла , поэтому, если это произойдет, это все равно что делать, cp -pа потом rmя собираюсь.
2rs2ts
9
Помните: shutil.move в Python 2.7.3 завершается ошибкой, если место назначения уже существует. Поэтому, если это возможно, либо перехватите ошибку, либо вручную удалите файл / dir, а затем выполните перемещение.
Дана
36

Для os.rename или shutil.move вам нужно будет импортировать модуль. Символ * не требуется для перемещения всех файлов.

У нас есть папка в / opt / awesome с именем source и одним файлом с именем awesome.txt.

in /opt/awesome
  ls
source
  ls source
awesome.txt

python 
>>> source = '/opt/awesome/source'
>>> destination = '/opt/awesome/destination'
>>> import os
>>> os.rename(source, destination)
>>> os.listdir('/opt/awesome')
['destination']

Мы использовали os.listdir, чтобы увидеть, что имя папки действительно изменилось. Вот шутиль, перемещающий пункт назначения обратно к источнику.

>>> import shutil
>>> shutil.move(destination, source)
>>> os.listdir('/opt/awesome/source')
['awesome.txt']

На этот раз я проверил внутри исходной папки, чтобы убедиться, что созданный мной файл awesome.txt существует. Это там :)

Теперь мы переместили папку и ее файлы из источника в место назначения и обратно.

jmontross
источник
4
docs.python.org/2/library/shutil.html Эта документация показывает, что вы изменили свои параметры для метода shutil.move.
mac10688
1
Я использовал место назначения и источник в обратном порядке, чтобы убедиться, что файлы перемещены из источника, а затем обратно в него ... Я мог видеть, как это неясно.
Jmontross
34

После Python 3.4 вы также можете использовать pathlibкласс Pathдля перемещения файла.

from pathlib import Path

Path("path/to/current/file.foo").rename("path/to/new/destination/for/file.foo")

https://docs.python.org/3.4/library/pathlib.html#pathlib.Path.rename

MoonFruit
источник
3
Импортировать «из pathlib import Path» работает хорошо :)
Touhid
14

Это то, что я использую в данный момент:

import os, shutil
path = "/volume1/Users/Transfer/"
moveto = "/volume1/Users/Drive_Transfer/"
files = os.listdir(path)
files.sort()
for f in files:
    src = path+f
    dst = moveto+f
    shutil.move(src,dst)

Теперь полностью функциональный. Надеюсь, это поможет вам.

Редактировать:

Я превратил это в функцию, которая принимает каталог источника и назначения, создает папку назначения, если она не существует, и перемещает файлы. Также позволяет фильтровать файлы src, например, если вы хотите только перемещать изображения, то вы используете шаблон '*.jpg', по умолчанию он перемещает все в каталоге

import os, shutil, pathlib, fnmatch

def move_dir(src: str, dst: str, pattern: str = '*'):
    if not os.path.isdir(dst):
        pathlib.Path(dst).mkdir(parents=True, exist_ok=True)
    for f in fnmatch.filter(os.listdir(src), pattern):
        shutil.move(os.path.join(src, f), os.path.join(dst, f))
Питер Влаар
источник
1
Вы можете легко превратить это в отфильтрованное движение с помощью fnmatch.filter (), см. Мое редактирование. Кроме того, лучше всего использовать os.path.join(parent_path, filename)вместо конкатенации строк, чтобы избежать кросс-платформенных проблем
iggy12345
11

Принятый ответ не является правильным, потому что вопрос не в переименовании файла в файл, а в перемещении многих файлов в каталог. shutil.moveбудет делать работу, но для этой цели os.renameбесполезно (как указано в комментариях), потому что пункт назначения должен иметь явное имя файла.

Хавьер Паласиос
источник
Не бесполезный, просто требует больше работы, чтобы заставить его перемещать несколько файлов. Вы можете получить имена файлов с помощью os.path.basename(my_file_path)и каталоги файлов с помощью os.path.dirname(my_file_path). Кроме того, ОП не очень ясно дал понять, хочет ли он переместить несколько файлов. Он упомянул перемещение только одного файла в вопросе, но его пример кода подразумевал перемещение нескольких файлов.
Жак Матье
2

Исходя из ответа, описанного здесь , использование subprocessявляется еще одним вариантом.

Что-то вроде этого:

subprocess.call("mv %s %s" % (source_files, destination_folder), shell=True)

Мне любопытно знать за и против этого метода по сравнению с shutil. Так как в моем случае я уже использую subprocessпо другим причинам, и, кажется, это работает, я склонен придерживаться этого.

Возможно, это зависит от системы?

Билл
источник
2
Я считаю, что это будет зависеть от системы. Я не вижу mvуспешного использования в операционной системе Windows.
Джошуа Шлихтинг
0

Это решение, которое не позволяет shellиспользовать mv.

import subprocess

source      = 'pathToCurrent/file.foo'
destination = 'pathToNew/file.foo'

p = subprocess.Popen(['mv', source, destination], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
res = p.communicate()[0].decode('utf-8').strip()

if p.returncode:
    print 'ERROR: ' + res
Alper
источник
-2
  import os,shutil

  current_path = "" ## source path

  new_path = "" ## destination path

  os.chdir(current_path)

  for files in os.listdir():

        os.rename(files, new_path+'{}'.format(f))
        shutil.move(files, new_path+'{}'.format(f)) ## to move files from 

другой диск отл. C: -> D:

Нед Сларк
источник
если вы используете Python3. # вы можете использовать новую f-строку intrerpolation: f"{new_path}{f}"но, учитывая, что в вашей строке нет статического текста, это может быть больше работы .... Я пытался привыкнуть к использованию ф-струн хотя.
Юзопи
Вы имеете в виду файл вместо f?
Матфея