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


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.