Python function that similar to bash find command
Question:
I have a dir structure like the following:
[me@mypc]$ tree .
.
├── set01
│ ├── 01
│ │ ├── p1-001a.png
│ │ ├── p1-001b.png
│ │ ├── p1-001c.png
│ │ ├── p1-001d.png
│ │ └── p1-001e.png
│ ├── 02
│ │ ├── p2-001a.png
│ │ ├── p2-001b.png
│ │ ├── p2-001c.png
│ │ ├── p2-001d.png
│ │ └── p2-001e.png
I would like to write a python script to rename all *a.png to 01.png, *b.png to 02.png, and so on. Frist I guess I have to use something similar to find . -name '*.png'
, and the most similar thing I found in python was os.walk
. However, in os.walk
I have to check every file, if it’s png, then I’ll concatenate it with it’s root, somehow not that elegant. I was wondering if there is a better way to do this? Thanks in advance.
Answers:
For a search pattern like that, you can probably get away with glob
.
from glob import glob
paths = glob('set01/*/*.png')
Check out genfind.py from David M. Beazley.
# genfind.py
#
# A function that generates files that match a given filename pattern
import os
import fnmatch
def gen_find(filepat,top):
for path, dirlist, filelist in os.walk(top):
for name in fnmatch.filter(filelist,filepat):
yield os.path.join(path,name)
# Example use
if __name__ == '__main__':
lognames = gen_find("access-log*","www")
for name in lognames:
print name
This can be done with the recursive glob provided by pathlib:
import pathlib
for p in pathlib.Path(".").rglob("*.png"):
print(p)
The package provides useful features for renaming files, too.
For reference:
- https://docs.python.org/3/library/pathlib.html#pathlib.Path.glob
- https://docs.python.org/3/library/pathlib.html#pathlib.Path.rglob
- https://docs.python.org/3/library/pathlib.html#pathlib.Path.rename
- https://docs.python.org/3/library/pathlib.html#pathlib.Path.replace
- https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.with_stem
For Python 2 os.walk
could be used to traverse the directory tree.
Example:
import os
for dpath, dnames, fnames in os.walk("."):
for i, fname in enumerate([os.path.join(dpath, fname) for fname in fnames]):
if fname.endswith(".png"):
#os.rename(fname, os.path.join(dpath, "%04d.png" % i))
print "mv %s %s" % (fname, os.path.join(dpath, "%04d.png" % i))
These days, pathlib is a convenient option.
I have a dir structure like the following:
[me@mypc]$ tree .
.
├── set01
│ ├── 01
│ │ ├── p1-001a.png
│ │ ├── p1-001b.png
│ │ ├── p1-001c.png
│ │ ├── p1-001d.png
│ │ └── p1-001e.png
│ ├── 02
│ │ ├── p2-001a.png
│ │ ├── p2-001b.png
│ │ ├── p2-001c.png
│ │ ├── p2-001d.png
│ │ └── p2-001e.png
I would like to write a python script to rename all *a.png to 01.png, *b.png to 02.png, and so on. Frist I guess I have to use something similar to find . -name '*.png'
, and the most similar thing I found in python was os.walk
. However, in os.walk
I have to check every file, if it’s png, then I’ll concatenate it with it’s root, somehow not that elegant. I was wondering if there is a better way to do this? Thanks in advance.
For a search pattern like that, you can probably get away with glob
.
from glob import glob
paths = glob('set01/*/*.png')
Check out genfind.py from David M. Beazley.
# genfind.py
#
# A function that generates files that match a given filename pattern
import os
import fnmatch
def gen_find(filepat,top):
for path, dirlist, filelist in os.walk(top):
for name in fnmatch.filter(filelist,filepat):
yield os.path.join(path,name)
# Example use
if __name__ == '__main__':
lognames = gen_find("access-log*","www")
for name in lognames:
print name
This can be done with the recursive glob provided by pathlib:
import pathlib
for p in pathlib.Path(".").rglob("*.png"):
print(p)
The package provides useful features for renaming files, too.
For reference:
- https://docs.python.org/3/library/pathlib.html#pathlib.Path.glob
- https://docs.python.org/3/library/pathlib.html#pathlib.Path.rglob
- https://docs.python.org/3/library/pathlib.html#pathlib.Path.rename
- https://docs.python.org/3/library/pathlib.html#pathlib.Path.replace
- https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.with_stem
For Python 2 os.walk
could be used to traverse the directory tree.
Example:
import os
for dpath, dnames, fnames in os.walk("."):
for i, fname in enumerate([os.path.join(dpath, fname) for fname in fnames]):
if fname.endswith(".png"):
#os.rename(fname, os.path.join(dpath, "%04d.png" % i))
print "mv %s %s" % (fname, os.path.join(dpath, "%04d.png" % i))
These days, pathlib is a convenient option.