Jak przenieść plik?


907

Zajrzałem do osinterfejsu Pythona , ale nie byłem w stanie znaleźć metody przeniesienia pliku. Jak mam zrobić odpowiednik $ mv ...w Pythonie?

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

1
Dla tych z Was zna GNU Coreutils' mvpolecenia , Python shutil.movema jeden przypadek krawędzi, gdzie shutil.moveróżni funkcyjnych. Idź tutaj, aby napisać cały tekst . W skrócie, Python shutil.movezgłosi wyjątek (ale gnu-coreutils mvtego nie zrobi), gdy miejscem docelowym jest katalog, a katalog ma już plik o tej samej nazwie co źródło (ponownie, aby uzyskać więcej informacji, zobacz link podany w poprzednim zdaniu ).
— Trevor Boyd Smith

3
Jak o os.system("mv file1 file2")?
— John Strood

Odpowiedzi:


1337

os.rename(), shutil.move()lubos.replace()

Wszystkie stosują tę samą składnię:

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

Pamiętaj, że musisz podać nazwę pliku ( file.foo) zarówno w argumentach źródłowym, jak i docelowym. Jeśli zostanie zmieniony, nazwa pliku zostanie zmieniona, a także przeniesiona.

Zauważ również, że w pierwszych dwóch przypadkach katalog, w którym tworzony jest nowy plik, musi już istnieć. W systemie Windows plik o tej nazwie nie może istnieć lub zostanie zgłoszony wyjątek, ale os.replace()po cichu zastąpi plik nawet w takim przypadku.

Jak zauważono w komentarzach do innych odpowiedzi, w większości przypadków shutil.movepo prostu dzwoni os.rename. Jeśli jednak miejsce docelowe znajduje się na innym dysku niż źródło, skopiuje, a następnie usunie plik źródłowy.


8
Czy jestem jedynym, który uważa, że ​​os.rename nie działa dla katalogów? Cytuję: „Jeśli dst jest katalogiem, podniesiony zostanie błąd OSError”.
— Fabian

33
shutil.movedziała dla katalogów. Możesz użyć ścieżki względnej shutil.move(f.name, "tmp/")lub pełnej shutil.move(f.name, "/Users/hello/tmp/"), nie używaj jej ~ na ścieżce, zaznaczone w python2.7.9, Mac OS X.
— dlaczegoisyoung 21.04.15

3
~jest konstrukcją powłoki i nie ma nic wspólnego ze ścieżkami plików jako takimi, jak złą konwencją. Jeśli naprawdę chcesz zaangażować swój katalog domowy, użyj os.getenv('HOME')zamiast tego, łącząc go z częściami pożądanej ścieżki, jeśli to konieczne.
— AMN

15
Zawsze możesz użyć, os.path.expanduser()aby poprawnie rozwinąć „ ~” zgodnie z regułami specyficznymi dla systemu operacyjnego. Znacznie fajniejsze, ponieważ %HOME%nie zawsze jest ustawione w systemie Windows.
— ig0774

14
os.renamenie obsługuje plików na różnych urządzeniach. Użyj, shutil.movejeśli nie masz pewności, czy plik źródłowy i docelowy znajdują się na tym samym urządzeniu.
— Giuseppe Scrivano

244

Mimo os.rename()i shutil.move()oba będą zmieniać nazwy plików, najbliższe jest polecenie Univ mv shutil.move(). Różnica polega na tym, os.rename()że nie działa, jeśli źródło i miejsce docelowe znajdują się na różnych dyskach, a shutil.move()nie obchodzi, na jakim dysku znajdują się pliki.


75
shutil.move()używa, os.rename()jeśli miejsce docelowe znajduje się w bieżącym systemie plików. W przeciwnym razie shutil.move()kopiuje źródło do miejsca docelowego za pomocą, shutil.copy2()a następnie usuwa źródło.
— przerwa w linii

8
Uważaj, aby zdać sobie sprawę, że shutil.copy2()nie można skopiować wszystkich metadanych pliku , więc jeśli tak się stanie, to tak, jakby to zrobić, cp -pa następnie rm, jak się okazuje,
— 2rs2ts

9
Pamiętaj: shutil.move w Pythonie 2.7.3 kończy się niepowodzeniem, jeśli miejsce docelowe już istnieje. Jeśli to możliwe, albo złap błąd, albo ręcznie usuń plik / katalog, a następnie wykonaj ruch.
— Dana

36

W przypadku nazwy os.rename lub shutil.move musisz zaimportować moduł. Do przeniesienia wszystkich plików nie jest wymagany znak *.

Mamy folder w / opt / awesome o nazwie source z jednym plikiem o nazwie 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']

Użyliśmy os.listdir, aby zobaczyć, że nazwa folderu faktycznie się zmieniła. Oto shutil przenoszący cel z powrotem do źródła.

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

Tym razem sprawdziłem w folderze źródłowym, aby upewnić się, że utworzony plik awesome.txt istnieje. Jest tam :)

Teraz przenieśliśmy folder i jego pliki ze źródła do miejsca docelowego iz powrotem.


4
docs.python.org/2/library/shutil.html Ta dokumentacja pokazuje, że zmieniłeś parametry dla metody shutil.move.
— mac10688

1
Użyłem odwróconego miejsca docelowego i źródła, aby zobaczyć, że pliki zostały przeniesione ze źródła, a następnie z powrotem do niego .... Widziałem, jak to jest niejasne.
— jmontross


14

Z tego właśnie korzystam:

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)

Teraz w pełni funkcjonalny. Mam nadzieję, że to ci pomoże.

Edytować:

Przekształciłem to w funkcję, która akceptuje katalog źródłowy i docelowy, tworząc folder docelowy, jeśli nie istnieje, i przenosi pliki. Pozwala również na filtrowanie plików src, na przykład jeśli chcesz tylko przenosić obrazy, następnie używasz wzorca '*.jpg', domyślnie przenosi wszystko w katalogu

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
Możesz łatwo zmienić to w filtrowany ruch za pomocą fnmatch.filter (), zobacz moją edycję. Ponadto najlepiej jest używać os.path.join(parent_path, filename)zamiast konkatenacji łańcuchów, aby uniknąć problemów międzyplatformowych
— iggy12345

11

Przyjęta odpowiedź nie jest prawidłowa, ponieważ pytanie nie dotyczy zmiany nazwy pliku na plik, ale przeniesienie wielu plików do katalogu. shutil.movewykona pracę, ale w tym celu os.renamejest bezużyteczny (jak podano w komentarzach), ponieważ miejsce docelowe musi mieć jawną nazwę pliku.


Nie jest to bezużyteczne, po prostu wymaga więcej pracy, aby przenieść wiele plików. Możesz uzyskać nazwy plików os.path.basename(my_file_path)i katalogi plików za pomocą os.path.dirname(my_file_path). Ponadto OP nie wyjaśnił, czy chce przenieść wiele plików. Wspomniał o przeniesieniu tylko jednego pliku w pytaniu, ale jego przykładowy kod sugerował przeniesienie wielu plików.
— Jacques Mathieu

2

W oparciu o opisaną tutaj odpowiedź użycie subprocessto kolejna opcja.

Coś takiego:

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

Jestem ciekawy, jakie są zalety i wady tej metody w porównaniu do shutil. Ponieważ w moim przypadku używam już subprocessz innych powodów i wydaje się, że działa, jestem skłonny się z tym trzymać.

Czy może zależy to od systemu?


2
Wierzę, że byłoby to zależne od systemu. Nie widzę, aby mvbył używany z powodzeniem w systemie operacyjnym Windows.
— Joshua Schlichting

0

Jest to rozwiązanie, które nie umożliwia shellkorzystania 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 

inny dysk np. C: -> D:


jeśli używasz Python3. # możesz użyć nowej interpolacji ciągów f: f"{new_path}{f}"ale biorąc pod uwagę, że nie masz statycznego tekstu w ciągu, może to być więcej pracy ... Próbowałem przyzwyczaić się do używania f-stringi.
— jusopi

Masz na myśli plik zamiast f?
— Matthew
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.