ez

A cross-platform Python utility library for easy shell interaction and common programming tasks on Linux, macOS, and Windows.
Installation
pip install ez
Requires Python 3.11+.
Quick Start
from ez import *
# File operations
files = ls('~/Documents', r'\.py$')
cp('source.txt', '~/backup/')
mv('old_name.txt', 'new_name.txt')
rm('temp/')
# Path utilities
print(cwd()) # current working directory
print(jp('~', 'Documents', 'file')) # join path components
print(sp('/path/to/file.txt')) # => ['/path/to', 'file', '.txt']
# Execute shell commands
execute('ls -la')
output = execute2('echo hello')
esp('echo %s', 'world')
# Read/write spreadsheets
data = readx('data.xlsx')
savex('output.xlsx', data, header=['Name', 'Age'])
Function Catalog
Generated by ez/prepublish.py from the same source as ez.__doc__.
Runtime and Errors
| Function |
Aliases |
Description |
ShellDebug |
debug |
Set the shell debug mode used by file and process operations. |
HTTP and Retries
| Function |
Aliases |
Description |
retry |
|
Retry a callable with a timeout and randomized waiting intervals. |
rget |
|
Fetch an HTTP response as JSON when possible, otherwise as text. |
rgetraw |
|
Make a retrying HTTP GET request and return its response. |
rgetfile |
|
Download an HTTP response body to a file, retrying failed requests. |
Paths
| Function |
Aliases |
Description |
pwd |
cwd |
Imported from os.getcwd. |
fullpath |
fp |
Resolve an absolute path, expanding variables, user directories, and wildcards. |
csd |
|
Return the running script directory, or the working directory in interactive mode. |
stepfolder |
|
Change to a sibling folder selected by step or regular expression. |
csf |
|
Return the running script filename without its extension. |
parentdir |
pr |
Return the parent directory of a path. |
joinpath |
jp |
Join path components, supporting vectorized arguments. |
splitpath |
sp |
Split a path into directory, filename, and extension. |
extpath |
ep |
Replace a path's filename extension, supporting vectorized arguments. |
cleanpath |
xp |
Clean the filename component of a path. |
Strings and Regular Expressions
| Function |
Aliases |
Description |
trim |
|
Normalize spaces and trim leading or trailing characters. |
quote |
|
Wrap a value in double quotes. |
join |
|
Join strings or a sequence using a separator. |
sprintf |
|
Format a string using supplied values or the caller's local variables. |
regexp |
|
Find regular expression matches, split text, or match from the start. |
regexpi |
|
Find regular expression matches without case sensitivity. |
regexprep |
|
Replace regular expression matches in a string. |
regexprepi |
|
Replace regular expression matches without case sensitivity. |
Directories and Files
| Function |
Aliases |
Description |
cd |
|
Change the working directory. |
ce |
|
Changes to working directory in Finder |
cf |
|
Changes to working directory in Path Finder, QSpace, or Finder (auto-detected) |
ls |
|
List matching files in a directory. |
lsd |
|
List matching subdirectories. |
fls |
|
List matching files recursively from a directory tree. |
flsd |
|
List matching folders recursively from a directory tree. |
clorox |
clx |
Find or delete operating-system metadata files. |
mkdir |
|
Create a directory and any missing parents. |
exists |
|
Test whether a path or wildcard pattern exists. |
rn |
|
Rename a file or folder. |
trash |
|
Move a file or folder to trash. Requires: pip install Send2Trash |
rm |
|
Deletes a file or folder. |
cp |
|
Copies a source file or folder to destination. |
mv |
|
Moves a source file or folder to destination. |
lns |
|
Creates a soft link/symbolic link/shortcut. |
gapfile |
|
Finds missing and extra files based on a regex pattern. |
tree |
|
Print a directory tree, optionally including files or saving the output. |
lines |
|
Count lines in matching source files. |
Shell and Processes
| Function |
Aliases |
Description |
execute0 |
|
Run a shell command and capture its output. |
execute |
|
Run a shell command without capturing its output. |
esp0 |
|
Run a formatted shell command and capture its output. |
esp |
|
Run a formatted shell command without capturing its output. |
espR0 |
|
Run formatted R code and capture its output. |
espR |
|
Run formatted R code without capturing its output. |
espA |
|
Execute formatted AppleScript through a temporary script file. |
contextmanager |
|
Imported from contextlib.contextmanager. |
nooutput |
|
Temporarily suppress stdout, stderr in a context |
Console, System and Logging
| Function |
Aliases |
Description |
ppprint |
|
Imported from pprint.pprint. |
error |
|
Raise an exception with the supplied message. |
pprint |
|
Print colored text to the terminal. |
beep |
|
Beeps to notify user. |
where |
|
Print the location of a module, function, or Python interpreter. |
which |
|
Imported from shutil.which. |
doc |
help |
Print the docstring of a named module, class, or function. |
getos |
|
Return the operating system name. |
ver |
version |
Print the installed version of Python or a package. |
require |
|
Ensure a package is installed at the latest compatible or a specified version via pip or Conda. |
evaluate |
|
Evaluate a Python expression or execute a statement in the caller's scope. |
who |
whos |
List imported names in the requested scope. |
_setlog |
|
Enable or disable redirecting stdout to both a file and the terminal. |
logon |
|
Enable logging stdout to both a file and the terminal. |
clear |
|
Remove a module, optionally including submodules, from sys.modules. |
logoff |
|
Disable file logging and restore stdout. |
Randomness
| Function |
Aliases |
Description |
Randomize |
randomize |
Imported from random.seed. |
RandomizeArray |
randomizearray |
Imported from random.shuffle. |
Random |
|
Imported from random.randint. |
RandomChoice |
randomchoice |
Imported from random.choice. |
keygen |
|
Generate a random key. |
Permute |
permute |
Return all permutations of an iterable as a list. |
Time and Waiting
| Function |
Aliases |
Description |
sleep |
wait |
Imported from time.sleep. |
pause |
|
Wait for Enter; return False if interrupted with Ctrl+C. |
daylight |
|
Test whether a datetime is in daylight saving time in a timezone. |
Numbers and General Helpers
| Function |
Aliases |
Description |
iff |
ifelse |
Return one of two values according to an expression. |
round2 |
|
Round a number with a small adjustment for halfway values. |
num |
|
Convert a value to a number, optionally returning pandas.NA on failure. |
isempty |
|
Test for None, an empty value, or a missing numeric value. |
Collections
| Function |
Aliases |
Description |
replace |
|
Replace matching items in a list. |
remove |
|
Remove matching items from a list. |
sort |
|
Return a sorted copy of an iterable. |
chunk |
|
Split the list, xs, into n chunks. |
chunk2 |
|
Split a list into chunks of a requested size. |
is_iterable |
|
Test for an iterable, treating strings and tuples as atomic values. |
unique |
|
Return unique sequence elements in their original order. |
union |
|
Return the ordered union of two sequences. |
intersect |
|
Return the ordered intersection of two sequences. |
setdiff |
|
Return elements of the first sequence absent from the second, in order. |
setdiff2 |
|
Return the elements of seq1 that are absent from seq2. |
compare |
|
Print union, intersection, and uniqueness counts for two sequences. |
duplicated |
|
Find repeated list items or candidate duplicate files in a directory. |
Hashing
| Function |
Aliases |
Description |
hashes |
|
Hash or verify text with PBKDF2, or calculate a file's digest values. |
Data and File Formats
| Function |
Aliases |
Description |
readt |
|
Read a text file as a list of lines. |
xlcolconv |
|
Convert between Excel column numbers and letters. |
readx |
|
Read an Excel or CSV file into lists. |
savex |
writex |
Write tabular data to an Excel or CSV file. |
savexlist |
writexlist |
Write multiple pandas dataframes to sheets in an Excel workbook. |
readp |
|
Read a Parquet file into a pandas object. |
readplist |
|
Read and concatenate multiple Parquet files. |
mergep |
|
Merge matching Parquet files into one file. |
savep |
writep |
Save a pandas object as a Parquet file. |
savek |
writek |
Serialize an object to a pickle file. |
readk |
|
Load and return an object from a pickle file. |
readj |
|
Load JSON from a file. |
savej |
writej |
Save a value as JSON, encoding datetime values as ISO strings. |
savet |
writet |
Write a list of lines to a text file. |
savew |
writew |
Write lines and an optional heading to a Word document. |
Text and Encoding
| Function |
Aliases |
Description |
hanzifreq |
|
Count Chinese character frequencies in a text file. |
pinyinauthor |
|
Format author names as surname and initials for APA references. |
encoding_detect |
|
Guess the encoding of text or a file. |
encoding_convert |
|
Convert a file to UTF-8. |
Desktop and Keyboard Maestro
| Function |
Aliases |
Description |
opens |
|
Open files with their default application. |
vx |
|
Open a pandas dataframe in a spreadsheet application. |
getkmvar |
|
Read a Keyboard Maestro environment variable. |
setkmvar |
|
Set a Keyboard Maestro variable using AppleScript. |
runkm |
|
Run a Keyboard Maestro macro by UUID. |
playfirefoxmacro |
|
Run a UI.Vision browser macro in Firefox. |
msgbox |
|
Display a message using Keyboard Maestro. |
menubar |
|
Set Keyboard Maestro's menubar text. |
Office-to-Markdown Conversion
| Function |
Aliases |
Description |
_md_paths |
|
Resolve and validate input and output paths for document conversion. |
_md_write |
|
Write converted Markdown to a file or standard output. |
_md_ranges |
|
Parse a one-based comma-separated list of values and ranges. |
_md_load_office |
|
Load an Office document and normalize missing-member errors. |
pptx2md |
|
Convert a PowerPoint presentation to Markdown using MarkItDown. |
docx2md |
|
Convert a Word .docx document to Markdown using MarkItDown. |
xlsx2md |
|
Convert Excel .xlsx worksheets to Markdown tables using openpyxl. |
pdf2md |
|
Convert text-based PDF pages to Markdown using PyMuPDF and MarkItDown. |
_cli_input_files |
|
Resolve and validate input files for a batch conversion. |
_cli_output_files |
|
Build safe Markdown output paths for batch input files. |
_cli_batch |
|
Run a document conversion over the selected batch of input files. |
_cli |
|
Run an explicitly registered CLI tool; return an integer exit status. |
Office and PDF Utilities
| Function |
Aliases |
Description |
office_pptx_replace_font |
|
Replace fonts in a PowerPoint presentation. |
office_pptx_replace |
|
Replace matching text in a PowerPoint presentation. |
office_docx_replace |
|
Replace matching text in a Word document. |
office_pdf_from_docx |
|
Convert a Word document or folder of documents to PDF. |
office_pdf_from |
|
Convert documents to PDF using headless LibreOffice. |
office_doc2docx |
|
Convert documents to DOCX using headless LibreOffice. |
office_pdf_unlock |
|
Remove PDF password restrictions using Ghostscript. |
office_pdf_crop |
|
Crop PDF page margins. |
office_pdf_bookmarkrm |
|
Remove PDF bookmarks. |
office_pdf_compress |
|
Compress PDF files using Ghostscript. |
office_pdf_merge |
|
Merge PDF files in the requested order. |
office_pdf_autoname |
|
Rename PDFs using bibliographic metadata extracted from their text. |
AppleScript and Applications
| Function |
Aliases |
Description |
applescript_pages_replace |
|
Replace text in the active Pages document using AppleScript. |
applescript_pages_pdfactive |
|
Export the active Pages document to PDF using AppleScript. |
applescript_preview_moveactive |
|
Save and move the active Preview PDF using AppleScript. |
applescript_finder_alias |
|
Create a Finder alias using AppleScript. |
applescript_mail |
|
Compose or send an Apple Mail message using AppleScript. |
applescript_outlook |
|
Compose or send an Outlook message using AppleScript. |
Clipboard
| Function |
Aliases |
Description |
SetClip |
setclip |
Copy content to the clipboard. |
GetClip |
getclip |
Read and return the current clipboard contents. |
Mail and Microsoft Authentication
| Function |
Aliases |
Description |
Mail |
mail, gmail |
Send an email using yagmail. |
imapget |
|
Retrieve emails via IMAP using imap-tools. |
gmailget |
|
Retrieve Gmail messages matching the supplied filters. |
ymailget |
|
Retrieve Yahoo Mail messages matching the supplied filters. |
o365auth |
|
Authenticate to Microsoft 365 and return the account. |
outlook |
|
Send or draft a Microsoft 365 email. |
outlookget |
|
Retrieve Microsoft 365 messages from a folder. |
OneDrive
| Function |
Aliases |
Description |
onedrive_connect |
|
Resolve a OneDrive file or folder path to its remote object. |
onedrive_move |
|
Move a OneDrive file or folder to another folder. |
onedrive_copy |
|
Copy a OneDrive file or folder to another folder. |
onedrive_delete |
|
Move a OneDrive file or folder to the recycle bin. |
onedrive_rename |
|
Rename a OneDrive file or folder. |
onedrive_download |
|
Download a OneDrive file or folder. |
onedrive_upload |
|
Upload a local file to OneDrive, replacing an existing file if needed. |
onedrive_share |
|
Create a sharing link for a OneDrive item. |
onedrive_lsfile |
|
List files in a OneDrive folder. |
onedrive_lsfolder |
|
List subfolders in a OneDrive folder. |
onedrive_excel |
|
Open a OneDrive Excel workbook session and select a worksheet. |
onedrive_readx |
|
Read the used range of a OneDrive Excel worksheet. |
Password Management
| Function |
Aliases |
Description |
setpassword |
|
Store an account password in the km.py keyring service. |
getpassword |
|
Read an account password from the km.py keyring service. |
getpasswordbw |
|
Retrieve a Bitwarden item or selected field using its CLI. |
Keyboard and Mouse
| Function |
Aliases |
Description |
send |
|
Send keyboard keys or text with configurable delays and repetitions. |
_mouse |
|
Return randomized Bezier path points between two mouse positions. |
_move |
|
Move the mouse along a randomized Bezier path. |
moveclick |
|
Move to a point or randomized area location, then click the left mouse button. |
click |
|
Click the left mouse button the requested number of times. |
rclick |
|
Click the right mouse button the requested number of times. |
scroll |
|
Scroll the mouse by the supplied horizontal and vertical amounts. |
position |
|
Return the current mouse position. |
size |
|
Return the available display monitor bounds. |
Dropbox
| Function |
Aliases |
Description |
dropbox_spaceusage |
|
Return available, used, and total Dropbox space in gigabytes. |
upload |
|
Upload a local file to Dropbox. |
download |
|
Download a Dropbox file to a local path. |
_files_list_folder_all |
|
List all Dropbox entries in a folder, following continuation cursors. |
lsfile |
|
List Dropbox files in a folder, optionally recursively. |
lsfolder |
|
List Dropbox subfolders, optionally recursively. |
delfilefolder |
|
Delete a Dropbox file or folder. |
Google Drive
| Function |
Aliases |
Description |
gauth |
|
Authenticate to Google Drive and return the configured drive client. |
gdownload |
|
Export or download a Google Drive file. |
gupload |
|
Upload a file to Google Drive, updating the first matching title if present. |
gdelete |
|
Permanently delete a Drive file by its ID or name. |
gcopy |
|
Copy a Google Drive file. |
gmove |
|
Move a Google Drive file to another folder. |
gls |
|
List non-trashed files and folders in a Google Drive folder. |
gfileid |
|
Return the Drive file ID for the first file matching filename in folderid. |
Images and PDF Annotations
| Function |
Aliases |
Description |
gif |
|
Create an animated GIF from image files. |
pdf2gif |
|
Create an animated GIF from cropped PDF pages. |
pdfannot |
|
Extract PDF highlights and annotations into Markdown. |
Usage Details
Documents to Markdown
import ez
markdown = ez.pptx2md('talk.pptx') # prints to stdout and returns the Markdown
markdown = ez.pptx2md(
'talk.pptx', note=True, slides='1-3,5', markers=False,
images=True, output='talk.md', overwrite=True,
)
All four converters return the Markdown string and print it when output=None.
With output='file.md', they write UTF-8 instead of printing. Existing output files
raise FileExistsError unless overwrite=True; replacing the input document is
always rejected, including symlink/hard-link aliases.
PowerPoint
| Argument (default) |
CLI flag |
Effect |
note=False |
-n, --note |
Include speaker notes. |
slides=None |
-s, --slides |
Select 1-based slides, e.g. 1-3,5; default is all slides. |
markers=True |
--no-markers |
Remove <!-- Slide number: N --> comments and separate slides with ---. |
images=False |
--images |
Embed images as base64 data URIs instead of filename references. |
output=None |
-o, --output |
Write UTF-8 Markdown to a file instead of stdout. |
overwrite=False |
-f, --force |
Allow replacing an existing output file. |
Selections retain presentation order, ignore duplicates, and preserve original
slide numbers. Invalid or out-of-range selections raise ValueError. Existing
output files raise FileExistsError unless overwriting is enabled. The input
presentation is never overwritten. Filename image references do not extract
image files; use images=True for self-contained Markdown.
pptx2md talk.pptx -n -s 1-3,5 --images -o talk.md
pptx2md --help
Word
markdown = ez.docx2md('report.docx', images=True, output='report.md')
images=False is the default. Use --images to preserve complete base64 image
URIs; otherwise MarkItDown abbreviates them into unusable image references.
Supported headings, lists, tables, and links are converted, not exact page layout.
docx2md report.docx --images -o report.md
Excel
markdown = ez.xlsx2md(
'data.xlsx', sheets=['Annual Sales', 'Summary'], formulas=False,
headers=True, output='data.md',
)
| Argument (default) |
CLI flag |
Effect |
sheets=None |
-s, --sheets NAME [NAME ...] |
Select exact worksheet names; default is all worksheets, including hidden ones. |
formulas=False |
--formulas |
Emit formula strings instead of cached values. |
headers=True |
--no-headers |
Generate column-letter headers and include the first row as data. |
Selections retain workbook order and ignore duplicates; unknown names raise
ValueError. Each worksheet has a heading and a Markdown table; empty worksheets
have only a heading. Trailing empty rows/columns are omitted. Images, charts,
styles, and macros are not extracted; merged cells are not expanded.
Formulas are not evaluated. Missing cached formula values produce a warning
and empty cells. Calculate and save the workbook in Excel/LibreOffice first, or
use formulas=True to emit the formulas themselves.
xlsx2md data.xlsx --sheets "Annual Sales" Summary -o data.md
xlsx2md data.xlsx --formulas --no-headers
PDF
markdown = ez.pdf2md('paper.pdf', pages='1-3,5', markers=False, output='paper.md')
| Argument (default) |
CLI flag |
Effect |
pages=None |
-p, --pages |
Select 1-based page ranges; default is all pages. |
markers=True |
--no-markers |
Remove <!-- Page number: N --> comments and separate pages with ---. |
Selections retain document order and original page numbers. This is text-based
extraction, not OCR: scanned/blank pages can have no text. Images are not
extracted; exact layout/table reconstruction is not guaranteed. Decrypt PDFs
requiring a password before conversion.
pdf2md paper.pdf -p 1-3,5 -o paper.md
Batch conversion
The installed commands accept multiple files, folders, and wildcard patterns.
Each Python converter still processes one file per call.
pptx2md *.pptx --output-dir markdown --images
docx2md first.docx second.docx --output-dir markdown
pdf2md reports --recursive --output-dir markdown
pdf2md "reports/**/*.pdf" --recursive --output-dir markdown
xlsx2md workbooks --output-dir markdown --sheets Summary
- More than one distinct input requires
--output-dir DIR; -o FILE is only
for one input and cannot be combined with --output-dir.
- A single input without
--output-dir retains the original stdout/-o behavior.
- Folders are scanned for the command's file extension, case-insensitively.
Use
--recursive for nested folders or quoted ** patterns. Recursive
discovery does not follow directory symlinks.
- Output folders are created as needed. Structure is preserved relative to the
common ancestor of input roots: a folder's root is itself, an explicit file's
root is its parent, and a wildcard's root is its non-wildcard directory prefix.
For example,
pdf2md reports --recursive --output-dir markdown maps
reports/a/report.pdf to markdown/a/report.md. Explicit inputs
a/report.pdf b/report.pdf map to markdown/a/report.md and
markdown/b/report.md, rather than overwriting one another.
- Repeated files and file aliases are converted once. Outputs colliding with
another destination or any source document are rejected, even with
--force.
- All conversion options apply to every input. Discovery/conversion/output
failures are reported to stderr while other files continue. A final summary
reports succeeded/failed counts; any failure produces a nonzero exit status.
Unmatched patterns and folders with no matching files are errors, not silent
successes. Unexpected programming errors remain visible.
--force allows replacing existing output files; otherwise they are reported
as failures. Batch Markdown goes to files, not stdout.
Installed commands and future CLI tools
Install this version of the package to generate all four commands:
python -m pip install .
# Or, for local development:
python -m pip install -e .
Activate the Python environment containing ez, or put its executable directory
on PATH. All commands support -o/--output, -f/--force, and -h/--help.
Running any converter command without arguments shows help and exits successfully.
Importing or directly running ez/ez.py does not launch a converter CLI.
_CLI_COMMANDS in ez/ez.py is the single registry of exported tools. To expose
another tool, add its function and a registry entry with function, description,
arguments, notes, and examples; optional groups reuse argument groups.
Each argument is a pair of flag/name strings and an argparse-options dictionary.
Use the strings "str", "int", or "float" for typed arguments. Unspecified
options are omitted from the function call, preserving the function's defaults.
Command names may differ from function names; registered targets must accept the
parsed arguments as keywords. The dispatcher ignores normal return values and
exits successfully after a successful call.
Batch support is opt-in: the converter entries also specify batch metadata
(input parameter, supported extension, and expected document errors) and
use the shared batch argument group. Tools without this metadata retain normal
single-call dispatch.
setup.py reads the literal registry without importing runtime dependencies and
generates console entry points targeting the general _cli dispatcher. Reinstall
the package after adding a command. No new wrapper files or shell functions are
needed. Converter dependencies (MarkItDown, openpyxl, PyMuPDF, and python-pptx)
are already declared in the package.
Classes
JDict() is a custom ordered dictionary with convenient attribute access and
helper methods. Use help(JDict) for details. Moment(timezone) returns the
current datetime in a specified timezone, or a local naive datetime if omitted.
Pipe
Chain operations using a pipe-style syntax:
# Basic pipe
[1, 2, 3, 0] > ez.pipe | len | str
# Countdown example
ez.pipe | (range, -1) | reversed | ez.pipetools.foreach('{0}...') | ' '.join | '{0} boom'
General Notes
- Almost all path-related commands support
~, .., ., ?, and *. The exceptions are ls and fls, which use regular expressions for filtering.
- File operations target symbolic links themselves, not the underlying files they point to.
Maintaining the Function Catalog
The topic regions and function docstrings in ez/ez.py are the source
of truth for both the generated ez.__doc__ catalog and the README function
catalog. Both list the same topics, functions, aliases, and summaries.
Each module-level function belongs
to a topic region and a nested region named after the function. Keep a concise
description on the first line of its docstring; existing parameter details and
examples follow it. Keep function aliases inside the same topic. Imported
convenience functions inside topic regions are listed with their source module.
Class methods and nested functions are not cataloged.
ez/prepublish.py reads this structure using only the Python
standard library, without importing ez or its optional runtime dependencies.
It replaces only the module's __doc__ assignment and the README section between
the BEGIN GENERATED FUNCTION CATALOG and END GENERATED FUNCTION CATALOG
markers. Do not edit either generated catalog by hand; edit the source docstrings
or regions instead. Usage details outside the markers remain hand-maintained.
python ez/prepublish.py --docs-only # regenerate both catalogs; do not bump the version
python ez/prepublish.py --check-docs # exit nonzero if either catalog is stale or invalid
python ez/prepublish.py --help
Running the hook without flags regenerates both catalogs, then increments the
release version using the existing numbering scheme. A catalog-generation failure
prevents that increment. The paths are resolved relative to the hook, not the
current working directory.
Both publish.sh and Publish.app retain their
existing workflows and prepublish invocation. They are unchanged: their existing
package-path assumptions and lack of fail-fast handling still apply. Use the
direct check command above to validate documentation independently; do not run a
publisher merely to regenerate documentation.
Run the focused maintenance tests with:
python -m unittest discover -s tests
License
GNU Affero General Public License v3 or later (AGPLv3+)