Summary
The suggested changes are as follows:
- Use
os.getcwd() instead of "." since it doesn't seem to be resolved the way you want. This will be illustrated in the diagnostics function.
- Use relative path renaming by
os.chdir(root). Of course using correct absolute paths also works, but IMHO relative paths are just more elegant.
- Pass an unambiguous string into
os.walk() as others have mentioned.
Also note that topdown=False in os.walk() doesn't matter. Since you are not renaming directories, the directory structure will be invariant during os.walk().
Code Sample
Original file structure:
bill@Bill-deb:/mnt/ramdisk/test$ tree .
.
├── outer
│ ├── inner
│ │ └── innermost.txt
│ └── inner.txt
├── outer.txt
└── rename.py
Code:
# -*- coding: utf-8 -*-
import os
def renamefiles(path):
for root, dirs, files in os.walk(path, topdown=False):
for f in files:
# chdir before renaming
os.chdir(root)
if f != "rename.py": # avoid renaming this file
os.rename(f, "renamed.txt") # relative path, more elegant
renamefiles(os.getcwd()) # pass an unambiguous string
Resulted file structure:
bill@Bill-deb:/mnt/ramdisk/test$ tree .
.
├── outer
│ ├── inner
│ │ └── renamed.txt
│ └── renamed.txt
├── renamed.txt
└── rename.py
Tested under debian 8.6 64-bit, python 2.7.12 (Anaconda 4.1.1).
For Diagnostics
# -*- coding: utf-8 -*-
import os
def renamefiles_check(path):
for root, dirs, files in os.walk(path, topdown=False):
for f in files:
print "========="
print "os.getcwd() = {}".format(os.getcwd())
print "root = {}".format(root)
print "f = {}".format(f)
print "os.path.abspath(f) = {}".format(os.path.abspath(f))
print "os.path.join(root, f) = {}".format(os.path.join(root, f))
# renamefiles_check(".")
# renamefiles_check(os.getcwd())
The first few lines of renamefiles_check(".") are shown here:
os.getcwd() = /mnt/ramdisk/test
root = ./outer/inner
f = innermost.txt
os.path.abspath(f) = /mnt/ramdisk/test/innermost.txt
os.path.join(root, f) = ./outer/inner/innermost.txt
You can verify that:
The behavior os.path.abspath(f) is not desired (not to say it's wrong). It always binds to the parameter path that was passed into os.walk() instead of the path containing file f.
When "." is passed as path, the dot in os.path.join(root, f) is still not fully resolved.
The sample code avoids these ambiguities.