CLI-like Operations¶
The upathtools library provides a unified CLI-like interface for executing filesystem commands on both local and remote filesystems through UPath objects.
Overview¶
Instead of learning a new API for each filesystem operation, you can use familiar shell commands directly on UPath objects and filesystem instances:
from upath import UPath
path = UPath(".")
result = path.cli("grep TODO *.py -r")
result = path.cli("find . -name '*.py' -type f")
result = path.cli("ls -lah")
Available Commands¶
grep - Search file contents¶
Search for patterns in files, similar to Unix grep:
# Basic search
result = path.cli("grep pattern file.txt")
# Case-insensitive search
result = path.cli("grep TODO README.md -i")
# Recursive search with file pattern
result = path.cli("grep 'import os' . -r --include='*.py'")
# Fixed string search (no regex)
result = path.cli("grep 'function()' src/ -r -F")
# With context lines
result = path.cli("grep error log.txt -B 2 -A 2")
# Invert match
result = path.cli("grep test -v")
Supported options:
- -r, --recursive: Search recursively in directories
- -i, --ignore-case: Case-insensitive matching
- -v, --invert-match: Select non-matching lines
- -w, --whole-word: Match whole words only
- -F, --fixed-string: Treat pattern as fixed string, not regex
- -m, --max-count N: Stop after N matches per file
- --include PATTERN: Only search files matching glob pattern
- --exclude PATTERN: Skip files matching glob pattern
- -B N, --context-before N: Show N lines before match
- -A N, --context-after N: Show N lines after match
find - Search for files¶
Find files and directories matching criteria:
# Find all Python files
result = path.cli("find . -name '*.py'")
# Find files by type
result = path.cli("find . -type f") # files only
result = path.cli("find . -type d") # directories only
# Case-insensitive name search
result = path.cli("find . -iname 'readme*'")
# Limit depth
result = path.cli("find . -maxdepth 2")
result = path.cli("find . -mindepth 1 -maxdepth 3")
# Find by size
result = path.cli("find . -size-min 1000 -size-max 100000")
# Find using regex
result = path.cli("find . --regex '.*\\.py$'")
Supported options:
- -name PATTERN: Filename pattern (glob, case-sensitive)
- -iname PATTERN: Filename pattern (case-insensitive)
- -type [f|d]: File type (f=file, d=directory)
- -maxdepth N: Maximum directory depth
- -mindepth N: Minimum directory depth
- --size-min N: Minimum file size in bytes
- --size-max N: Maximum file size in bytes
- --regex PATTERN: Regex pattern for full path
head - Show first lines¶
Display the first N lines of a file:
# First 10 lines (default)
result = path.cli("head file.txt")
# First 20 lines
result = path.cli("head file.txt -n 20")
Supported options:
- -n N: Number of lines to show
tail - Show last lines¶
Display the last N lines of a file:
# Last 10 lines (default)
result = path.cli("tail file.txt")
# Last 50 lines
result = path.cli("tail log.txt -n 50")
Supported options:
- -n N: Number of lines to show
cat - Concatenate files¶
Display file contents:
# Single file
result = path.cli("cat file.txt")
# Multiple files
result = path.cli("cat file1.txt file2.txt file3.txt")
wc - Word count¶
Count lines, words, and characters:
result = path.cli("wc file.txt")
# Output: WcResult(path='file.txt', lines=100, words=500, chars=3000, bytes=3000)
ls - List directory contents¶
List files and directories:
# Basic listing
result = path.cli("ls")
# All files including hidden
result = path.cli("ls -a")
# Long format with details
result = path.cli("ls -l")
# Human-readable sizes
result = path.cli("ls -lh")
# Recursive listing
result = path.cli("ls -R")
# Sort by size or time
result = path.cli("ls -l --sort-by size")
result = path.cli("ls -l --sort-by mtime")
# Reverse sort
result = path.cli("ls -l --reverse")
Supported options:
- -a, --all: Include hidden files
- -l, --long: Long format with details
- -h, --human-readable: Human-readable file sizes
- -r, -R, --recursive: Recursive listing
- --sort-by [name|size|mtime]: Sort criteria
- --reverse: Reverse sort order
du - Disk usage¶
Estimate file space usage:
# Directory usage
result = path.cli("du .")
# Human-readable sizes
result = path.cli("du . -h")
# Summary only (total)
result = path.cli("du . -s")
# Max depth
result = path.cli("du . -d 2")
Supported options:
- -h, --human-readable: Human-readable sizes
- -s, --summarize: Show only total
- -d N, --max-depth N: Maximum depth to report
diff - Compare files¶
Show differences between two files:
result = path.cli("diff file1.txt file2.txt")
# Custom context lines
result = path.cli("diff file1.txt file2.txt --context-lines 5")
Working with Results¶
The CLI commands return a CLIResult object that can be used in multiple ways:
result = path.cli("grep TODO *.py -r")
# String representation
print(result)
# Iterate over results
for match in result:
print(match)
# Access raw data
data = result.data
Async Usage¶
For async filesystems and paths, use acli():
Using with Filesystems¶
CLI commands can also be executed on filesystem instances:
import fsspec
from upathtools.filesystems.base import BaseFileSystem
# Get a filesystem instance
fs = fsspec.filesystem("file")
# Execute commands (all paths are relative to filesystem root)
result = fs.cli("grep TODO /path/to/file.txt")
result = fs.cli("ls /some/directory -lh")
Examples¶
Search for TODO comments in a project¶
from upath import UPath
project = UPath(".")
todos = project.cli("grep TODO . -r --include='*.py'")
for match in todos:
print(f"{match.path}:{match.line_number}: {match.line}")
Find large files¶
large_files = path.cli("find . -type f --size-min 1000000")
for file in large_files:
print(f"{file.path}: {file.size} bytes")
Analyze log files¶
# Get last 100 lines
recent = path.cli("tail app.log -n 100")
# Count errors
errors = path.cli("grep ERROR app.log")
error_count = len(list(errors))
print(f"Found {error_count} errors")
Directory overview¶
# Get disk usage summary
usage = path.cli("du . -sh")
print(usage)
# List sorted by size
largest = path.cli("ls . -lh --sort-by size --reverse")
for entry in largest[:10]: # Top 10
print(f"{entry.size_human}\t{entry.name}")
Remote Filesystems¶
The CLI interface works seamlessly with remote filesystems:
from upath import UPath
# S3
s3_path = UPath("s3://bucket/prefix")
result = s3_path.cli("find . -name '*.json'")
# HTTP
http_path = UPath("https://example.com/data/")
result = http_path.cli("ls -l")
# Git
git_path = UPath("github://owner:repo@main/src")
result = git_path.cli("grep TODO . -r")
Notes¶
- All paths in commands are relative to the base path (the path object you call
.cli()on) - Absolute paths in commands (starting with
/) are resolved relative to the filesystem root - Pattern matching (glob, regex) uses Python's
fnmatchandremodules - Binary files are automatically detected and skipped by default in
grep - The interface mimics common Unix command behavior but may not support all options