GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |||||||||||||||||||||||||||
GeezerVison is showing zetcode.com — Python directory - create, rename, copy, move, list, and remove directories Python directorylast modified October 30, 2026 Python 3.15 In this article we show how to work with directories in Python. We create, rename, copy, move, remove, and list directories. Directory definitionA directory is an organizing unit in a computer's file system for storing and locating files. Directories are hierarchically organized into a tree of directories. Directories have parent-child relationships. A directory is sometimes also called a folder.
Python has functions for manipulating directories in the
Creating a directory
The create_dir.py
from pathlib import Path
p = Path('test')
p.mkdir()
The example creates the $ python create_dir.py
$ ls -d test
test
$ python create_dir.py
Traceback (most recent call last):
File "/home/user/python/create_dir.py", line 4, in <module>
p.mkdir()
~~~~~~~^^
File "/usr/lib/python3.15/pathlib/__init__.py", line 1210, in mkdir
os.mkdir(self, mode)
~~~~~~~~^^^^^^^^^^^^
FileExistsError: [Errno 17] File exists: 'test'
Ignoring existing directories
When we run the previous program twice, an exception is raised. If the
create_dir2.py
from pathlib import Path
p = Path('test')
p.mkdir(exist_ok=True)
print(f'{p} exists: {p.is_dir()}')
The
Checking with $ python create_dir2.py test exists: True Creating nested directories
With create_nested.py
from pathlib import Path
p = Path('reports/2026/10')
p.mkdir(parents=True, exist_ok=True)
for d in sorted(Path('reports').rglob('*')):
print(d)
The example creates the $ python create_nested.py reports/2026 reports/2026/10 Permissions of parent directories
The parent_mode.py
from pathlib import Path
Path('private/keys/ssh').mkdir(mode=0o700, parents=True)
Path('shared/keys/ssh').mkdir(mode=0o700, parents=True, parent_mode=0o750)
We create two paths with a private last directory. In the second call, the
parents get the $ python parent_mode.py $ stat -c '%A %n' private private/keys private/keys/ssh drwxr-xr-x private drwxr-xr-x private/keys drwx------ private/keys/ssh $ stat -c '%A %n' shared shared/keys shared/keys/ssh drwxr-x--- shared drwxr-x--- shared/keys drwx------ shared/keys/ssh Creating a temporary directory
The temp_dir.py
import tempfile
from pathlib import Path
with tempfile.TemporaryDirectory(prefix='build-') as tempdir:
print(f'created temporary directory {tempdir}')
p = Path(tempdir) / 'output.txt'
p.write_text('temporary data')
print(f'{p.name} exists: {p.exists()}')
print(f'directory exists: {Path(tempdir).exists()}')
We create a temporary directory with a name prefix and write a file into it.
After the
The directory is created in the system's temporary directory, which is
$ python temp_dir.py created temporary directory /tmp/build-3pud1rhl output.txt exists: True directory exists: False Renaming a directory
The rename_dir.py
from pathlib import Path
src = Path('test')
dest = src.rename('test2')
print(f'{src} renamed to {dest}')
print(src.exists(), dest.exists())
We rename the $ python rename_dir.py test renamed to test2 False True Removing a directory
A directory is removed with the remove_dir.py
import shutil
from pathlib import Path
Path('empty').mkdir()
Path('empty').rmdir()
print('removed empty directory')
full = Path('full')
full.mkdir()
(full / 'data.txt').write_text('some data')
try:
full.rmdir()
except OSError as e:
print(e)
shutil.rmtree(full)
print(f'{full} exists: {full.exists()}')
Removing a non-empty directory with $ python remove_dir.py removed empty directory [Errno 39] Directory not empty: 'full' full exists: False Copying a directory
The copy_dir.py
import shutil
from pathlib import Path
src = Path('projects')
dst = src.copy('projects-copy')
print(f'copied to {dst}')
shutil.copytree(src, 'projects-src', ignore=shutil.ignore_patterns('*.csv', '*.sh'))
We copy the $ python copy_dir.py copied to projects-copy $ find projects-copy -type f | sort projects-copy/README.md projects-copy/blog/app.py projects-copy/blog/templates/index.html projects-copy/data/users.csv projects-copy/notes.txt projects-copy/scripts/backup.py projects-copy/scripts/clean.sh $ find projects-src -type f | sort projects-src/README.md projects-src/blog/app.py projects-src/blog/templates/index.html projects-src/notes.txt projects-src/scripts/backup.py Moving a directory
The move_dir.py
import shutil
from pathlib import Path
dest = shutil.move('docs', 'docs2')
print(dest)
archive = Path('archive')
archive.mkdir()
moved = Path('docs2').move_into(archive)
print(moved)
We first move the $ mkdir docs $ touch docs/data.txt docs/names.csv docs/numbers.csv $ python move_dir.py docs2 archive/docs2 $ ls archive/docs2 data.txt names.csv numbers.csv Current working directory
The current_dir.py
import contextlib
import os
from pathlib import Path
print(f'Current working directory: {Path.cwd()}')
os.chdir('projects')
print(f'Current working directory: {Path.cwd()}')
os.chdir('..')
with contextlib.chdir('projects/blog'):
print(f'Inside the block: {Path.cwd()}')
print(Path('app.py').exists())
print(f'After the block: {Path.cwd()}')
We change the working directory with $ python current_dir.py Current working directory: /home/user/python Current working directory: /home/user/python/projects Inside the block: /home/user/python/projects/blog True After the block: /home/user/python Home directory
The home_dir.py
from pathlib import Path
print(Path.home())
print(Path('~/Documents/notes.txt').expanduser())
print(Path.home() / '.config')
The $ python home_dir.py /home/user /home/user/Documents/notes.txt /home/user/.config Directory parents
The parents.py
from pathlib import Path
path = Path('/home/user/python/projects/blog/templates')
print(f'The parent directory of {path} is {path.parent}')
print(f'The parent of the parent is {path.parent.parent}')
print(f'The third ancestor is {path.parents[2]}')
print('All the ancestors:')
for parent in path.parents:
print(parent)
print(path.name, path.parts)
The ancestors can be accessed by index; $ python parents.py
The parent directory of /home/user/python/projects/blog/templates is /home/user/python/projects/blog
The parent of the parent is /home/user/python/projects
The third ancestor is /home/user/python
All the ancestors:
/home/user/python/projects/blog
/home/user/python/projects
/home/user/python
/home/user
/home
/
templates ('/', 'home', 'user', 'python', 'projects', 'blog', 'templates')
Listing directory contents
The list_dir.py
from pathlib import Path
path = Path('projects')
for entry in sorted(path.iterdir()):
kind = 'dir ' if entry.is_dir() else 'file'
print(kind, entry.name)
The example lists the files and directories of the $ python list_dir.py file README.md dir blog dir data file notes.txt dir scripts Checking if a path is a directory
The list_dirs.py
from pathlib import Path
path = Path('projects')
dirs = [e.name for e in path.iterdir() if e.is_dir()]
files = [e.name for e in path.iterdir() if e.is_file()]
print('directories:', *sorted(dirs))
print('files:', *sorted(files))
We separate the immediate subdirectories of $ python list_dirs.py directories: blog data scripts files: README.md notes.txt Listing a directory recursively
The recursive.py
from pathlib import Path
path = Path('projects')
print('Python files:')
for e in sorted(path.rglob('*.py')):
print(e)
print('Top-level text files:')
for e in sorted(path.glob('*.txt')):
print(e)
print('Files one level down:')
for e in sorted(path.glob('*/*.*')):
print(e)
We find all Python files in the $ python recursive.py Python files: projects/blog/app.py projects/scripts/backup.py Top-level text files: projects/notes.txt Files one level down: projects/blog/app.py projects/data/users.csv projects/scripts/backup.py projects/scripts/clean.sh Walking a directory tree
The walk_dir.py
from pathlib import Path
for root, dirs, files in Path('projects').walk():
dirs.sort()
depth = len(root.parts) - 1
print(f'{" " * depth}{root.name}/')
for name in sorted(files):
size = (root / name).stat().st_size
print(f'{" " * (depth + 1)}{name} ({size} B)')
We print the tree with file sizes. Sorting the $ python walk_dir.py
projects/
README.md (35 B)
notes.txt (19 B)
blog/
app.py (100 B)
templates/
index.html (60 B)
data/
users.csv (44 B)
scripts/
backup.py (60 B)
clean.sh (31 B)
Directory size
The dir_size.py
import os
from pathlib import Path
def dir_size(path):
total = 0
with os.scandir(path) as entries:
for entry in entries:
if entry.is_file(follow_symlinks=False):
total += entry.stat(follow_symlinks=False).st_size
elif entry.is_dir(follow_symlinks=False):
total += dir_size(entry.path)
return total
for d in sorted(Path('projects').iterdir()):
if d.is_dir():
print(f'{d.name:10} {dir_size(d):5} B')
print(f'{"total":10} {dir_size("projects"):5} B')
files = [p for p in Path('projects').rglob('*') if p.is_file()]
print(f'{"rglob":10} {sum(p.stat().st_size for p in files):5} B')
The recursive $ python dir_size.py blog 160 B data 44 B scripts 91 B total 349 B rglob 349 B Checking paths
The check_dir.py
from pathlib import Path
for name in ['projects', 'projects/notes.txt', 'missing']:
p = Path(name)
print(f'{name:20} exists={p.exists()!s:5} is_dir={p.is_dir()!s:5} '
f'is_file={p.is_file()}')
empty = Path('empty')
empty.mkdir()
print(f'{empty} is empty: {not any(empty.iterdir())}')
print(f'projects is empty: {not any(Path("projects").iterdir())}')
To check if a directory is empty, we ask $ python check_dir.py projects exists=True is_dir=True is_file=False projects/notes.txt exists=True is_dir=False is_file=True missing exists=False is_dir=False is_file=False empty is empty: True projects is empty: False Sourcepathlib - Object-oriented filesystem paths - Python documentation In this article we have worked with directories in Python. AuthorMy name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming. List all Python tutorials. | |||||||||||||||||||||||||||
| You are visitor 01402520 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |