Як перемістити файл?


907

Я заглянув у osінтерфейс Python , але не зміг знайти спосіб переміщення файлу. Як я можу зробити еквівалент $ mv ...у Python?

>>> source_files = '/PATH/TO/FOLDER/*'
>>> destination_folder = 'PATH/TO/FOLDER'
>>> # equivalent of $ mv source_files destination_folder

1
для тих, хто вам знайомий з командою gnu-coreutilsmv , python shutil.moveмає один крайній випадок, коли shutil.moveфункція відрізняється. Перейдіть сюди, щоб повністю написати . Коротше кажучи, Python shutil.moveпідніме виняток (але gnu-coreutils mvне буде), коли ваш пункт призначення - це каталог, а в каталозі вже є файл з тим же ім'ям, що і джерело (знову для отримання додаткової інформації див. Посилання, подане в попередньому реченні ).
— Тревор Бойд Сміт

3
Як щодо os.system("mv file1 file2")?
— Джон Строд

Відповіді:


1337

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. Однак якщо місце призначення знаходиться на іншому диску, ніж джерело, воно замість цього скопіює та видалить вихідний файл.


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()буде перейменовувати файли, команда, найближча до команди Univ 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 з джерелом з одним файлом під назвою 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']

Цього разу я перевірив всередині вихідної папки, щоб переконатися, що створений я створений файл.txt. Це там :)

Тепер ми перемістили папку та її файли з джерела до місця призначення та знову.


4
docs.python.org/2/library/shutil.html Ця документація показує, що ви переключили параметри на метод shutil.move.
— mac10688

1
Я використовував цільове призначення та джерело перевернуто, щоб побачити, що файли переміщуються від джерела, а потім назад до нього .... Я міг бачити, як це незрозуміло.
— jmontross


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

-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-string: f"{new_path}{f}"але, враховуючи, що у вас немає статичного тексту в рядку, це може бути більше роботи .... Я намагаюся ввійти в звичку використовувати f-рядки, хоча.
— jusopi

Ви маєте на увазі файл замість f?
— Матвій
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.