如何在Python中检查文件是否存在并重命名它

0 投票
2 回答
1742 浏览
提问于 2025-04-19 07:40

我想找到一种更符合Python风格的方法来实现我现在的代码功能。我相信一定有更好的做法。我想要搜索到filename-10,如果这个文件存在,就创建一个叫做filename-11的文件。

如果你能帮忙,那就太好了。

编辑:2014年9月1日晚上9:46

import re
import os
f=open('/Users/jakerandall/Desktop/Data Collection Python/temp.cnc', 'r')
text = re.search(r"(?<!\d)\d{4,5}(?!\d)", f.read())
JobNumber = text.string[text.start():text.end()]


if os.path.isfile("/Users/jakerandall/Desktop/Data Collection Python/%s-10.cnc" % JobNumber):
    f=open("/Users/jakerandall/Desktop/Data Collection Python/%s-11.cnc"  % JobNumber, 'w+b')
    f.close()
    print '1'
elif os.path.isfile("/Users/jakerandall/Desktop/Data Collection Python/%s-9.cnc" % JobNumber):
    f=open('/Users/jakerandall/Desktop/Data Collection Python/%s-10.cnc' % JobNumber, 'w+b')
    f.close()
    print '2'
elif os.path.isfile("/Users/jakerandall/Desktop/Data Collection Python/%s-8.cnc" % JobNumber):
    f=open('/Users/jakerandall/Desktop/Data Collection Python/%s-9.cnc' % JobNumber, 'w+b')
    f.close()
    print '3'
elif os.path.isfile("/Users/jakerandall/Desktop/Data Collection Python/%s-7.cnc" % JobNumber):
    f=open('/Users/jakerandall/Desktop/Data Collection Python/%s-8.cnc' % JobNumber, 'w+b')
    f.close()
    print '4'
elif os.path.isfile("/Users/jakerandall/Desktop/Data Collection Python/%s-6.cnc" % JobNumber):
    f=open('/Users/jakerandall/Desktop/Data Collection Python/%s-7.cnc' % JobNumber, 'w+b')
    f.close()
    print '5'
elif os.path.isfile("/Users/jakerandall/Desktop/Data Collection Python/%s-5.cnc" % JobNumber):
    f=open('/Users/jakerandall/Desktop/Data Collection Python/%s-6.cnc' % JobNumber, 'w+b')
    f.close()
    print '6'
elif os.path.isfile("/Users/jakerandall/Desktop/Data Collection Python/%s-4.cnc" % JobNumber):
    f=open('/Users/jakerandall/Desktop/Data Collection Python/%s-5.cnc' % JobNumber, 'w+b')
    f.close()
    print '7'
elif os.path.isfile("/Users/jakerandall/Desktop/Data Collection Python/%s-3.cnc" % JobNumber):
    f=open('/Users/jakerandall/Desktop/Data Collection Python/%s-4.cnc' % JobNumber, 'w+b')
    f.close()
    print '8'
elif os.path.isfile("/Users/jakerandall/Desktop/Data Collection Python/%s-2.cnc" % JobNumber):
    f=open('/Users/jakerandall/Desktop/Data Collection Python/%s-3.cnc' % JobNumber, 'w+b')
    f.close()
    print '9'
elif os.path.isfile("/Users/jakerandall/Desktop/Data Collection Python/%s-1.cnc" % JobNumber):
    f=open('/Users/jakerandall/Desktop/Data Collection Python/%s-2.cnc' % JobNumber, 'w+b')
    f.close()
    print '10'
elif os.path.isfile("/Users/jakerandall/Desktop/Data Collection Python/%s.cnc" % JobNumber):
    f=open('/Users/jakerandall/Desktop/Data Collection Python/%s-1.cnc' % JobNumber, 'w+b')
    f.close()
    print '11'
else:
    f=open('/Users/jakerandall/Desktop/Data Collection Python/%s.cnc' % JobNumber, 'w+b')
    f.close()
    print '12'
f.close()

2 个回答

0

我其实写过类似的东西!不过我现在是凭记忆在说。这种方式作为一个独立的模块很有用,因为以这种方式备份文件是相当常见的。

# /backup_dash_one.py

import os, glob, re

def backup(full_path, num_backups=None):
    """Usage: backup('example/pathname.ext', [num_backups])
    returns: example/pathname-1.ext, advances all backups by 1

    Given example/pathname.ext, creates backups named
    example/pathname-1.ext, -2.ext, -3.ext until there are
    as many backups as num_backups, purging those older."""

    head, tail = os.path.split(full_path)
    tailname, tailext = os.path.splitext(tail)

    def find_backup_num(path):
        return int(re.search(r"-(\d+)\.[^.\\/]*", path).group(1))

    paths = sorted(glob.glob(os.path.join(head,tailname)+"-*"+tailext),
                   key=find_backup_num)
    for path in reversed(paths[:]):
        head_tail, backup_num, ext, _* = re.split(r"-(\d+)(\.[^\\./]*)$", path)
        new_path = head_tail + "-" + str(int(backup_num)+1) + ext

        with open(path) as infile, open(new_path,'w') as outfile):
            for line in infile:
                outfile.write(line)
        if new_path not in paths:
            paths.append(new_path)

    while num_backups and len(paths) > num_backups:
        os.remove(paths[-1])
        paths.pop()

如果我有时间的话,我真的应该多花点时间在这上面,做更多的研究,可能会做成这样:

import glob, os

    class BackupFile(object):
    def __init__(self, path, mode="w", num_backups=None):
        self.num_backups = num_backups
        path_filename, ext = os.path.splitext(path)
        self.backups = glob.glob(path_filename+"-*"+ext)
        self.backups.sort(key=self.find_backup_num)
        self.backup()
        self.purge()
        with open(path_filename+"-1"+ext, 'w') as backup,\
             open(path, 'r') as original:
            for line in original:
                backup.write(line)
        self.f = open(path, mode)

    def find_backup_num(self,filename):
        return int(os.path.splitext(filename)[0].split('-')[-1])
    def backup(self):
        for path in reversed(self.backups[:]):
            head_num,ext = os.path.splitext(path)
            *head,num = head_num.split('-')
            new_path = "{}-{}{}".format('-'.join(head),
                            int(num)+1,
                            ext)
            with open(new_path, 'w') as newfile, \
                 open(path, 'r') as oldfile:
                for line in oldfile:
                    newfile.write(line)
            if new_path not in self.backups:
                self.backups.append(new_path)
    def purge(self):
        while self.num_backups and len(self.backups) > self.num_backups:
            os.remove(self.backups.pop())
    def __enter__(self):
        return self.f
    def __exit__(self, exc_type, exc_value, exc_traceback):
        self.f.close()

所以你可以直接这样做:

with BackupFile("path/to/file/that/needs/backups.txt", 'r+', num_backups=12) as f:
    make_change(f)
# ta-da it's backed up!

不过我其实没怎么测试过这个,所以我猜可能会有一些问题 :)

1

我们来看看更简单的做法:

import glob

file_directory = '/Users/jakerandall/Desktop/Data Collection Python/'
files = glob.glob('{}{}*.cnc'.format(file_directory, JobNumber))

现在,files 将会是一个包含实际存在于目录中的文件名的列表,这些文件名符合你的模式。

你可以检查这个列表的长度,然后:

  1. 如果列表是空的,创建第一个文件,文件名就是 '{}.cnc'.format(JobNumber)
  2. 如果列表的长度是11,你需要创建第11个文件(因为这个模式会匹配第一个文件,也就是没有任何 - 的那个,所以长度为11意味着最后一个文件是 -10.cnc)。
  3. 否则,你想要的文件就是 1 减去列表的长度。所以如果列表有5个项目,意味着最后一个文件是 -4.cnc(因为这个模式也会匹配第一个文件)。

你还需要检查一下能否打开这些文件,因为运行这个Python脚本的用户可能没有足够的权限。

下面是一个把这些内容结合在一起的例子:

import glob

file_directory = '/Users/jakerandall/Desktop/Data Collection Python/'
files = glob.glob('{}{}*.cnc'.format(file_directory, JobNumber))

# Start by assuming there are no files:
filename = '{}.cnc'.format(JobNumber)
if len(files) <= 11:
   # If there are less than 11 files, we need
   # to use the existing file, and overwrite it
   # If there are 4 files, in the directory, our
   # list will have a length of 5:
   # The original file, and then four files from -1, to -4
   # In this case, we want to use file 4, which is 1 less than
   # the length of the list:
   filename = '{}-{}.cnc'.format(JobNumber, len(files)-1)
else:
   # If we reach this point, it means
   # there were more than 10 files that match the
   # pattern. We want to use the next file,
   # which is next number higher, which is also the length
   # of the list, since it will include the first file.
   # So if the last file is -20, the list will have 20 files (from -1, to -20)
   # plus the original file, which has no - in the filename, giving
   # a length of 21, which also happens to be the number of the file
   # we want to create :)
   filename = '{}-{}.cnc'.format(JobNumber, len(files))

# Now, try to create the file
try:
   f = open(filename, 'w+b')
except IOError:
   print('Cannot create {}, check permissions?'.format(filename)) 

撰写回答