Dosya nasıl taşınır?


909

Python osarayüzüne baktım , ancak bir dosyayı taşımak için bir yöntem bulamadım. $ mv ...Python'da eşdeğerini nasıl yaparım ?

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

1
aşina o sizin için gnu-coreutils mvkomuta , piton en shutil.movebir kenar durumda nerede bulunur shutil.movefonksiyon farklıdır. Tam yazmak için buraya gidin . Özetle,shutil.movemv hedefiniz bir dizin olduğunda ve dizin zaten kaynakla aynı ada sahip bir dosya olduğunda Python'lar bir istisna oluşturur (ancak gnu-coreutils olmaz) ).
Trevor Boyd Smith

3
Nasıl os.system("mv file1 file2")?
John Strood

Yanıtlar:


1340

os.rename(), shutil.move()Ya daos.replace()

Hepsi aynı sözdizimini kullanır:

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

Dosya adını ( file.foo) hem kaynak hem de hedef bağımsız değişkenlerine eklemeniz gerektiğini unutmayın . Değiştirilirse, dosya yeniden adlandırılır ve taşınır.

Ayrıca ilk iki durumda yeni dosyanın oluşturulduğu dizinin zaten mevcut olması gerektiğini unutmayın. Windows'da, bu ada sahip bir dosya olmamalıdır veya bir istisna yükseltilir, ancak os.replace()bu durumda bile bir dosyayı sessizce değiştirir.

Diğer cevaplarla ilgili yorumlarda belirtildiği gibi, çoğu durumda shutil.movesadece arar os.rename. Ancak, hedef kaynaktan farklı bir disk üzerindeyse, kaynak dosyayı kopyalayıp silecektir.


8
Os.rename'in dizinler için çalışmadığını düşünen tek kişi ben miyim? Ben alıntı: "Eğer dst bir dizin ise, OSError yükseltilecek."
Fabian

33
shutil.movedizinler için çalışır. Sen göreli yol kullanabilirsiniz shutil.move(f.name, "tmp/")veya tam yol shutil.move(f.name, "/Users/hello/tmp/"), kullanmayın ~ yolunda, Mac OS X python2.7.9 teslim
whyisyoung

3
~bir kabuk yapısıdır ve yanlış yerleştirilmiş bir kural dışında, dosya yollarıyla hiçbir ilgisi yoktur. Ana dizininizi gerçekten dahil etmek istiyorsanız, os.getenv('HOME')bunun yerine, gerekirse, istediğiniz yolun bölümleriyle birleştirin.
amn

15
os.path.expanduser()' ~' İşletim sistemine özgü kurallara göre uygun şekilde genişletmek için her zaman kullanabilirsiniz . %HOME%Her zaman Windows'ta ayarlanmadığından çok daha temiz .
ig0774

14
os.renamefarklı cihazlardaki dosyaları işlemez. shutil.moveKaynak ve hedef dosyanın aynı cihazda olduğundan emin değilseniz kullanın .
Giuseppe Scrivano

244

Her ne kadar os.rename()ve shutil.move()her iki adlandırma dosyalarınız, Unix mv komutu en yakın olan komuttur shutil.move(). Fark, os.rename()kaynak ve hedef farklı disklerde ise shutil.move()çalışmazken, dosyaların hangi diskte olduğunu umursamaz.


75
shutil.move()os.rename()hedef geçerli dosya sisteminde ise kullanır . Aksi takdirde, shutil.move()kaynağı kullanarak kaynağı hedefe kopyalar shutil.copy2()ve ardından kaynağı kaldırır.
satır sonu

8
shutil.copy2()Tüm dosya meta verilerini kopyalayamayacağını anlamaya özen gösterin , bu durumda böyle bir şey olur cp -pve sonra rmtoplarım.
2rs2ts

9
Unutmayın: hedef zaten varsa Python 2.7.3'teki shutil.move başarısız olur. Bu nedenle, mümkünse hatayı yakalayın veya dosyayı / dizini el ile kaldırın, sonra hareketi yapın.
Dana

36

Os.rename veya shutil.move için modülü içe aktarmanız gerekir. Tüm dosyaların taşınabilmesi için * karakteri gerekmez.

/ Opt / awesome'da kaynak olarak adlandırılan ve awesome.txt adlı bir dosyaya sahip bir klasörünüz var.

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']

Aslında klasör adının değiştiğini görmek için os.listdir komutunu kullandık. İşte hedefi kaynağa geri götüren kapı.

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

Bu sefer oluşturduğum awesome.txt dosyasının var olduğundan emin olmak için kaynak klasörünü kontrol ettim. Orada :)

Şimdi bir klasörü ve dosyalarını bir kaynaktan bir hedefe taşıdık ve tekrar geri taşıdık.


4
docs.python.org/2/library/shutil.html Bu belgeler, parametrelerinizi shutil.move yöntemi için değiştirdiğinizi gösterir.
mac10688

1
Ben hedef kaynak ve dosyaları kaynaktan hareket ve daha sonra geri taşındığını görmek için tersini kullandım .... Bu nasıl belirsiz olduğunu görebiliyordu.
jmontross


14

Şu anda kullanıyorum:

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)

Şimdi tamamen işlevsel. Umarım bu size yardımcı olur.

Düzenle:

Bunu, bir kaynak ve hedef dizini kabul eden, yoksa hedef klasörü oluşturan ve dosyaları hareket ettiren bir işleve çevirdim. Ayrıca src dosyalarının filtrelenmesine izin verir, örneğin sadece görüntüleri taşımak istiyorsanız, deseni kullanırsınız, '*.jpg'varsayılan olarak dizindeki her şeyi taşır

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 () öğesini kullanarak bunu filtrelenmiş bir harekete kolayca dönüştürebilirsiniz, bkz. Düzenleme. Ayrıca, os.path.join(parent_path, filename)platformlar arası sorunları önlemek için dize birleştirme yerine kullanmak en iyisidir
iggy12345

11

Kabul edilen cevap doğru değildir, çünkü soru bir dosyayı bir dosyaya yeniden adlandırmak değil, birçok dosyayı bir dizine taşımakla ilgilidir. shutil.moveancak bu amaçla os.renameişe yaramaz (yorumlarda belirtildiği gibi) hedefin açık bir dosya adına sahip olması gerekir.


Yararsız değil, sadece birden fazla dosyayı taşıması için daha fazla iş gerektiriyor. İle dosya adlarını os.path.basename(my_file_path)ve ile dosya dizinlerini alabilirsiniz os.path.dirname(my_file_path). Ayrıca, birden fazla dosyayı taşımak istiyorsa OP tarafından çok açıklığa kavuşmamıştı. Soruda sadece bir dosya taşıdığından söz etti, ancak örnek kodu birden fazla dosyayı taşımayı ima etti.
Jacques Mathieu

2

Burada açıklanan cevaba dayanarak , kullanmak subprocessbaşka bir seçenektir.

Bunun gibi bir şey:

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

Bu yöntemin pro ve conlarını kıyasla merak ediyorum shutil. Benim durumumda zaten subprocessbaşka nedenlerden dolayı kullanıyorum ve işe yarıyor gibi gözüküyor.

Belki sisteme bağlı mı?


2
Bunun sisteme bağlı olacağına inanıyorum. mvWindows işletim sisteminde başarıyla kullanıldığını görmüyorum .
Joshua Schlichting

0

Bu etkinleştirir gelmez çözümdür shellkullanarak 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 

farklı disk ex. C: -> D:


Eğer Python3 f"{new_path}{f}"kullanıyorsanız. f-dizeleri olsa.
jusopi

Şunu mu demek istediniz: f yerine dosya?
Matthew
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.