简体   繁体   中英

How to check if a file exists and if so rename it in python

I am looking for a more pythonic way to do what my code does currently. I'm sure there is a better way to do this. I would like to search up until filename-10, and if that exists create a file called filename-11.

If you can help that would be great.

EDIT: 9/1/14 9:46 PM

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

How about something simpler:

import glob

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

Now files will be a list of file names that actually exist in the directory and match your pattern.

You can check the length of this list, and then:

  1. If its empty, create the first file, which is just '{}.cnc'.format(JobNumber) .
  2. If the length of the list is equal to 11, you need to create file number 11 (because the pattern will match the first file, the one without any - , so a length of 11 means the last file is -10.cnc ).
  3. Otherwise, the file you want is 1-the length of the list. So if the list has 5 items, it means the last file is -4.cnc (because the pattern will also match the very first file).

You'll still need to see if you can open them, because the user running the Python script may not have sufficient permissions.

Here is an example putting all that together:

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

I've actually written something like this! I'm working from memory though. This is useful as a separate module, since backing up files in such a way is fairly common.

# /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()

Personally if I had the time I really OUGHT to devote to this I'd do a bit more research and do something like:

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

So you could just do:

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

However I haven't had much of a chance to test that at all, so my guess is that there's something quite wrong with it :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM