2014-03-27 19 views
0

我有一個腳本可以從預先確定的網頁列表中下載文件(pdf,docs等)。如果文件名已存在,我想編輯我的腳本以更改尾隨_x的文件名稱,因爲可能來自不同頁面的文件將共享相同的文件名,但包含不同的內容,並且urlretrieve()似乎會自動覆蓋現有文件。更改文件的名稱,直到它是唯一的

到目前爲止,我有:

urlfile = 'https://www.foo.com/foo/foo/foo.pdf' 
filename = urlfile.split('/')[-1] 
filename = foo.pdf 
if os.path.exists(filename): 
    filename = filename('.')[0] + '_' + 1 

,對於一個發生做工精細,但它看起來像一個後foo_1.pdf將開始保存爲foo_1_1.pdf,等等。我想將文件保存爲foo_1.pdffoo_2.pdf等等。

任何人都可以指出我正確的方向如何確保文件名以正確的方式存儲在腳本運行?

謝謝。

+1

代替'if'使用'while'並增加你追加的索引(而不是'1') – fredtantini

+0

你的代碼示例不能運行,請提供一個short ,有效的程序可以顯示您遇到的問題。請參閱http://stackoverflow.com/help/mcve或http://SSCCE.ORG/。 –

回答

4

所以,你要的是這樣的:

curName = "foo_0.pdf" 

    while os.path.exists(curName): 
     num = int(curName.split('.')[0].split('_')[1]) 
     curName = "foo_{}.pdf".format(str(num+1)) 

這裏的總體方案:

  1. 假設你從第一個文件名啓動(foo_0.pdf
  2. 檢查是否存在該名稱是採取
  3. 如果是,重複名稱1
  4. 繼續循環,直到你fi找到一個名不採取

一種選擇:生成正在使用的文件號碼的清單,並根據需要更新。如果它被分類,你可以說name = "foo_{}.pdf".format(flist[-1]+1)。這樣做的好處是您不必每次都運行所有文件(如上述解決方案那樣)。但是,您需要保留內存中的數字列表。此外,這不會填補空缺的數字

0
import os 
def uniquify(path, sep=''): 
    path = os.path.normpath(path) 
    num = 0 
    newpath = path 
    dirname, basename = os.path.split(path) 
    filename, ext = os.path.splitext(basename) 
    while os.path.exists(newpath): 
     newpath = os.path.join(dirname, '{f}{s}{n:d}{e}' 
           .format(f=filename, s=sep, n=num, e=ext)) 
     num += 1 
    return newpath 

filename = uniquify('foo.pdf', sep='_') 

可能出現的問題與此有:

  1. 如果調用相同 路徑uniquify很多數千次,以後每次通話可由於 while-loop每次開始從num=0開始檢查,因此會稍微慢一些。
  2. uniquify是脆弱的,其中一個文件可能不存在 當時os.path.exists被稱爲競爭條件,但可能在您使用uniquify返回的值 時間存在。使用 tempfile.NamedTemporaryFile可以避免此問題。你不會得到 增量編號,但你會得到具有唯一名稱的文件, 保證不存在。您可以使用參數prefix至 指定文件的原始名稱。例如,

    import tempfile 
    import os  
    def uniquify(path, sep='_', mode='w'): 
        path = os.path.normpath(path) 
        if os.path.exists(path): 
         dirname, basename = os.path.split(path) 
         filename, ext = os.path.splitext(basename) 
         return tempfile.NamedTemporaryFile(prefix=filename+sep, suffix=ext, delete=False, 
                  dir=dirname, mode=mode) 
        else: 
         return open(path, mode) 
    

    這可能是像這樣使用:

    In [141]: f = uniquify('/tmp/foo.pdf')  
    In [142]: f.name 
    Out[142]: '/tmp/foo_34cvy1.pdf' 
    

    請注意,以防止競爭條件,打開的文件句柄 - 不僅僅是文件的名稱 - 返回。

1

爲什麼不直接使用tempfile module

fileobj = tempfile.NamedTemporaryFile(suffix='.pdf', prefix='', delete = False) 

現在你的文件名會在fileobj.name可用,你可以操縱你的心臟的內容。作爲一個額外的好處,這是跨平臺的。

0

由於您正在處理多個頁面,這看起來更像是一個「全局歸檔」而不是每個頁面的歸檔。對於每個頁面的存檔,我會回答去從@wnnmaw

對於全局存檔,我會採取不同的計算策略...

  1. 每個文件名
  2. 商店創建一個目錄目錄中的文件爲「1」+分機
  3. 將當前「number」寫入目錄爲「_files.txt」
  4. 其他文件寫爲2,3,4等,並將值增加到_files .txt

這樣做的好處:

  • 該目錄的原始文件名。如果您不斷將「Example-1.pdf」轉換爲「Example-2.pdf」,您可能會遇到下載真實的「Example-2.pdf」的情況,並且無法將其與原始文件名相關聯。
  • 您可以通過讀取_files.txt或計算目錄中文件的數量來獲取類似命名文件的數量。

就個人而言,我也建議存儲分層桶裝系統中的文件,這樣你就不會有太多的文件/在任何一個目錄的目錄(數百個文件,使得它惱人的用戶,數千的文件會影響操作系統性能)。分段系統可能會將文件名轉換爲十六進制,然後將文件放入`/%s /%s /%s「%(十六進制[0:3],十六進制[3:6],文件名)。給你更均勻的字符分配