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.