2009-05-07 200 views
9

我正在編寫一個Python備份腳本,我需要找到目錄(及其子目錄)中最舊的文件。我還需要將其過濾到* .avi文件中。在目錄中查找最舊的文件(遞歸)

該腳本將始終在Linux機器上運行。有什麼方法可以在Python中執行,或者運行一些shell命令會更好嗎?

目前我正在運行df以獲得特定分區上的可用空間,並且如果少於5 GB可用空間,我想要開始刪除最早的*.avi文件,直到滿足該條件。

+1

等待如何使用du獲得空閒空間?這隻會告訴用法AFAIK。 – 2009-05-08 00:32:18

+0

對不起,意思是不是du。 – 2009-05-08 00:40:13

+1

你確定它不是df? :P – 2009-05-08 00:41:48

回答

21

嗯。娜迪婭的回答更接近你要求的意思是;然而,在一棵樹上發現了(單)最早的文件,試試這個:

import os 
def oldest_file_in_tree(rootfolder, extension=".avi"): 
    return min(
     (os.path.join(dirname, filename) 
     for dirname, dirnames, filenames in os.walk(rootfolder) 
     for filename in filenames 
     if filename.endswith(extension)), 
     key=lambda fn: os.stat(fn).st_mtime) 

而在稍加修改,就可以得到n最早的文件(類似Nadia的答案):

import os, heapq 
def oldest_files_in_tree(rootfolder, count=1, extension=".avi"): 
    return heapq.nsmallest(count, 
     (os.path.join(dirname, filename) 
     for dirname, dirnames, filenames in os.walk(rootfolder) 
     for filename in filenames 
     if filename.endswith(extension)), 
     key=lambda fn: os.stat(fn).st_mtime) 

請注意,使用.endswith方法允許調用爲:

oldest_files_in_tree("/home/user", 20, (".avi", ".mov")) 

選擇多個擴展名。

最後,你應該要文件的完整列表,按照修改時間排序,以儘可能多地刪除根據需要自由空間,這裏的一些代碼:

import os 
def files_to_delete(rootfolder, extension=".avi"): 
    return sorted(
     (os.path.join(dirname, filename) 
     for dirname, dirnames, filenames in os.walk(rootfolder) 
     for filename in filenames 
     if filename.endswith(extension)), 
     key=lambda fn: os.stat(fn).st_mtime), 
     reverse=True) 

並注意reverse=True帶來的列表末尾的最舊文件,以便下一個要刪除的文件只需執行file_list.pop()

順便說一句,對於一個完整的解決方案,以你的問題,因爲你是在Linux上,其中os.statvfs可用運行,你可以這樣做:

import os 
def free_space_up_to(free_bytes_required, rootfolder, extension=".avi"): 
    file_list= files_to_delete(rootfolder, extension) 
    while file_list: 
     statv= os.statvfs(rootfolder) 
     if statv.f_bfree*statv.f_bsize >= free_bytes_required: 
      break 
     os.remove(file_list.pop()) 

statvfs.f_bfree是設備空閒塊和statvfs.f_bsize是塊大小。我們採用rootfolder statvfs,因此請注意指向其他設備的任何符號鏈接,我們可以刪除多個文件,而不實際釋放此設備中的空間。

UPDATE(複製胡安評論):

取決於操作系統和文件系統實現,您可能希望通過f_frsize而不是f_bsize繁殖f_bfree。在一些實現中,後者是優選的I/O請求大小。例如,在我剛剛測試的FreeBSD 9系統上,f_frsize是4096,f_bsize是16384. POSIX表示塊計數字段「以f_frsize爲單位」(請參見http://pubs.opengroup.org/onlinepubs/9699919799//basedefs/sys_statvfs.h.html

+1

根據操作系統和文件系統的實現,您可能希望將'f_bfree'乘以'f_frsize'而不是'f_bsize'。在一些實現中,後者是優選的I/O請求大小。例如,在我剛剛測試的FreeBSD 9系統上,'f_frsize'是4096,'f_bsize'是16384. POSIX表示塊計數字段是「以f_frsize爲單位」 - http://pubs.opengroup.org/onlinepubs/ 9699919799 // basedefs/sys_statvfs.h.html – Juan 2015-05-23 21:39:11

+0

@Juan非常感謝你! – tzot 2015-05-25 06:15:37

2

查看linux命令find

或者,this post將ls和tail一起管道刪除目錄中最舊的文件。這可以在沒有足夠可用空間的情況下循環完成。

僅供參考,下面是做它(跟隨鏈接,更多的選擇和討論)shell代碼:

ls -t -r -1 /path/to/files | head --lines 1 | xargs rm 
13

要做到這一點在Python中,你可以使用os.walk(path)超過文件遞歸迭代,和st_sizest_mtime屬性os.stat(filename)來獲取文件大小和修改時間。

10

您可以使用statfnmatch模塊一起找到文件

ST_MTIME參考,最後的修改時間。你可以選擇另一個值,如果你想

import os, stat, fnmatch 
file_list = [] 
for filename in os.listdir('.'): 
    if fnmatch.fnmatch(filename, '*.avi'): 
     file_list.append((os.stat(filename)[stat.ST_MTIME], filename)) 

然後你可以按時間排序和刪除根據它。

file_list.sort(key=lambda a: a[0]) 
0

os module提供了在Python中獲取目錄列表和文件信息所需的功能。我發現os.walk對遞歸遍歷目錄特別有用,os.stat會給你每個條目的詳細信息(包括修改時間)。

您可以通過簡單的shell命令輕鬆完成此操作。這對你是否有效取決於你想要對結果做什麼。

7

我認爲最簡單的方法是使用find和ls -t(按時間排序文件)。

東西沿着這些線路應該做的伎倆(刪除指定目錄下的最古老的AVI文件)

find/-name "*.avi" | xargs ls -t | tail -n 1 | xargs rm 

步步....

查找/ -name 「* .AVI」 - 從根目錄開始遞歸查找所有avi文件

xargs ls -t - 按修改時間找到的所有文件,從最新到最舊。

尾-n 1 - 搶在列表的最後一個文件(最早)

xargs的RM - 並刪除它

+0

他提到在循環中運行它。由於'find'往往是一個昂貴的操作,因此保留'xargs ls'的結果(可能是一個數組變量)並從中一次提取文件名可能是一個好主意。 – 2009-05-08 00:29:02

+0

或許用find和grep替換find? – 2009-05-08 00:58:27

2

這是另一個Python公式, -school相比其他一些,但很容易修改,並處理沒有匹配的文件,而不引發異常的情況。

import os 

def find_oldest_file(dirname="..", extension=".avi"): 
    oldest_file, oldest_time = None, None 
    for dirpath, dirs, files in os.walk(dirname): 
     for filename in files: 
      file_path = os.path.join(dirpath, filename) 
      file_time = os.stat(file_path).st_mtime 
       if file_path.endswith(extension) and (file_time<oldest_time or oldest_time is None): 
       oldest_file, oldest_time = file_path, file_time 
    return oldest_file, oldest_time 

print find_oldest_file() 
相關問題