abn
abn

Reputation: 1373

Rename files based on an input list Python

I have a bunch of files in a directory. They are automatically downloaded with the following names:

new.pdb
new(1).pdb
new(2).pdb and so on

I have a list of the actual filenames like:

AAA
BBB
CCC

I want a way to rename the files with their corresponding names in the list where new.pdb would be AAA.pdb, new(1).pdb would be BBB.pdb and so on. I'd really appreciate if you could give me a hint before you down vote. I've tried well enough to solve this but couldn't. I've tried this so far. But the issue with the following code is that a few files may download faster than the ones that started before them. So it doensn't rename as I wanted.

    infiles = filter(os.path.isfile, os.listdir(os.getcwd()))
    infiles = [os.path.join(os.getcwd(), f) for f in infiles] 
    infiles.sort(key=lambda x: os.path.getmtime(x))
    last_file = infiles[-1]
    if rename_files.endswith(".pdb"):
        os.rename(last_file, directory_name+".pdb")

Upvotes: 2

Views: 1712

Answers (1)

Amadan
Amadan

Reputation: 198314

The first three lines are correct.

However, for the for <variable> in <collection> construct to work, the <collection> needs to be a collection. last_file is string, thus a collection of characters; and it is impossible for a single character to end with .pdb.

Assuming rename_files is the list of new names, you want this after your first three lines:

infiles = (infile for infile in infiles if infile.endswith(".pdb"))
for infile, outfile in zip(infiles, rename_files):
    os.rename(infile, outfile + ".pdb")

zip will create a list of pairs from lists, so you first find all pdb files, pair them up with new names, then rename each according to the pair.

EDIT: if you want to go by the file names rather by your original mtime, you'll need to extract that number and sort by it:

def get_rank(infile):
    m = re.search(r'(?:\((\d+)\))[^()]*', infile)
    if m:
        return int(m.group(1))
    return 0 
infiles = filter(os.path.isfile, os.listdir(os.getcwd()))
infiles = [os.path.join(os.getcwd(), f) for f in infiles if f.endswith('.txt')]
filerank = (get_rank(infile) for infile in infiles)
renames = zip(filerank, infiles, rename_files)
renames.sort(key=lambda x: x[0])
for _, infile, outfile in renames:
    os.rename(infile, outfile + ".pdb")

Upvotes: 4

Related Questions