Rename a directory with a filename inside with Python

paugrana :

I am trying to rename several directories with the name of the first file inside them.

I am trying to:

  1. List the files inside a folder.
  2. Identify the directories.
  3. For each directory, access it, grab the name of the first file inside and rename the directory with such name.

This is what I got so far but it is not working. I know the code is wrong but before fixing the code I would like to know if the logic is right. Can anyone help please?

import os

for (root, dirs, files) in os.walk('.'):
    print(f'Found directory: {dirpath}')
    dirlist = []
    for d_idx, d in enumerate(dirlist):
        print(d)
    filelist = []
    for f_idex, f in enumerate(filelist):
        files.append(f)[1] 
        print(f)
    os.rename(d, f)

Thank you!

jdehesa :

There are a few problems in your code:

  1. You are renaming directories as you iterate them with os.walk. This is not a good idea, os.walk gives you a generator, meaning it creates elements as you iterate them, so renaming things within the loop will confuse it.
  2. Both for d_idx, d in enumerate(dirlist): and for f_idex, f in enumerate(filelist): iterate over variables that are declared to be empty lists in the line before, so those loops don't do anything. Also, within the second one, files.append(f) would append f to the list files, but the [1] at the end means "get the second element (remeber Python indexing is 0-based) of the value returned by the append function" - but append does not return anything (it modifies the list, not returns a new list), so that would fail (and you are not using the value read by [1] anyway, so it would not do anything).
  3. In os.rename(d, f), first, since the loops before do not ever run, d and f will not have a value, but also, assuming both d and f came from dirs and files, they would be given as paths relative to their parents, not to your current directory (.), so the renaming would fail.

This code should work as you want:

import os

# List of paths to rename
renames = []
# Walk current dir
for (root, dirs, files) in os.walk('.'):
    # Skip this dir (cannot rename current directory)
    if root == '.': continue
    # Add renaming to list
    renames.append((root, files[0]))
# Iterate renaming list in reverse order so deepest dirs are renamed first
for root, new_name in reversed(renames):
    # Make new full dir name (relative to current directory)
    new_full_name = os.path.join(os.path.dirname(root), new_name)
    # Rename
    os.rename(root, new_full_name)

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=19396&siteId=1