我正在编写Python备份脚本,我需要在目录(及其子目录)中找到最旧的文件。我还需要将其过滤为* .avi文件。
该脚本将始终在Linux计算机上运行。有没有办法在Python中执行它或者运行一些shell命令会更好?
目前我正在运行df
以获取特定分区上的可用空间,如果可用空间少于5千兆字节,我想开始删除最早的*.avi
文件,直到条件得到满足。
答案 0 :(得分:22)
嗯。 Nadia的回答更接近你的意思要求;但是,要查找树中的(单个)最旧文件,请尝试以下操作:
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,因此请注意指向其他设备的任何符号链接,我们可以删除许多文件而不会实际释放此设备中的空间。
更新(由Juan复制评论):
根据操作系统和文件系统的实现,您可能希望将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)
答案 1 :(得分:13)
要在Python中执行此操作,您可以使用os.walk(path)
以递归方式对文件进行迭代,并使用os.stat(filename)
的st_size
和st_mtime
属性来获取文件大小和修改时间。
答案 2 :(得分:10)
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])
答案 3 :(得分:7)
我认为最简单的方法是使用find和ls -t(按时间排序文件)。
沿着这些方向应该做的事情(删除指定目录下最旧的avi文件)
find / -name "*.avi" | xargs ls -t | tail -n 1 | xargs rm
一步一步......
find / -name“* .avi” - 从根目录开始递归查找所有avi文件
xargs ls -t - 对修改时间找到的所有文件进行排序,从最新到最旧。
tail -n 1 - 抓取列表中的最后一个文件(最旧的)
xargs rm - 并将其删除
答案 4 :(得分:3)
这是另一个Python公式,与其他一些相比有点老派,但很容易修改,并且处理不匹配文件的情况而不会引发异常。
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()
答案 5 :(得分:2)
查看linux命令find
。
或者,this post将ls和tail连接在一起以删除目录中最旧的文件。这可以在没有足够可用空间的情况下在循环中完成。
供参考,这是执行此操作的shell代码(请点击链接以获取更多选择和讨论):
ls -t -r -1 /path/to/files | head --lines 1 | xargs rm
答案 6 :(得分:0)