cheat sheet
Python One-Liners
Useful Python one-liners runnable directly from the shell with python -c or python -m. No file creation needed.
Python One-Liners
All examples run from your terminal — no Python file needed. Assumes python points to Python 3.
Hello, World
python -c "print('Hello, World!')"
Output:
Hello, World!
Current timestamp
python -c "from datetime import datetime; print(datetime.now().isoformat())"
Output:
2026-04-25T14:32:07.843221
JSON pretty-print from stdin
Pipe any JSON to Python for readable output:
echo '{"name":"Alice","age":30,"active":true}' \
| python -c "import sys,json; print(json.dumps(json.load(sys.stdin), indent=2))"
Output:
{
"name": "Alice",
"age": 30,
"active": true
}
Base64 encode / decode
python -c "import base64; print(base64.b64encode(b'hello world').decode())"
python -c "import base64; print(base64.b64decode('aGVsbG8gd29ybGQ=').decode())"
Output:
aGVsbG8gd29ybGQ=
hello world
URL encode / decode
python -c "from urllib.parse import quote; print(quote('hello world & more'))"
python -c "from urllib.parse import unquote; print(unquote('hello%20world%20%26%20more'))"
Output:
hello%20world%20%26%20more
hello world & more
Static file server
Serve the current directory on port 8080:
python -m http.server 8080
Output:
Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...
127.0.0.1 - - [25/Apr/2026 14:00:00] "GET / HTTP/1.1" 200 -
Add
--directory /path/to/dirto serve a specific directory instead of the current one.
Benchmark a snippet
python -m timeit -n 100000 "sum(range(100))"
Output:
100000 loops, best of 5: 2.38 usec per loop
Count lines / words in stdin
cat /etc/hosts | python -c "import sys; lines=sys.stdin.readlines(); print(f'{len(lines)} lines, {sum(len(l.split()) for l in lines)} words')"
Output:
23 lines, 62 words
Generate a random password
python -c "import secrets, string; print(secrets.token_urlsafe(16))"
Output:
Xt7mK3pN2qRsWvYu
Generate a UUID
python -c "import uuid; print(uuid.uuid4())"
Output:
3f7c4b2e-1a8d-4e9f-b0c3-72d5e1f6a309
SHA-256 hash of a string
python -c "import hashlib; print(hashlib.sha256(b'hello').hexdigest())"
Output:
2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
List pip packages as JSON
pip list --format=json | python -c "import sys,json; pkgs=json.load(sys.stdin); [print(p['name'],p['version']) for p in pkgs[:5]]"
Output:
certifi 2024.2.2
charset-normalizer 3.3.2
click 8.1.7
fastapi 0.111.1
httpx 0.27.0
Flatten a nested list
python -c "
nested = [[1,2],[3,[4,5]],6]
flat = list(__import__('itertools').chain.from_iterable(x if isinstance(x,list) else [x] for x in nested))
print(flat)
"
Output:
[1, 2, 3, [4, 5], 6]
Quick CSV to JSON
python -c "
import csv, json, sys
reader = csv.DictReader(sys.stdin)
print(json.dumps(list(reader), indent=2))
" << 'EOF'
name,age,city
Alice,30,NYC
Bob,25,LA
EOF
Output:
[
{
"name": "Alice",
"age": "30",
"city": "NYC"
},
{
"name": "Bob",
"age": "25",
"city": "LA"
}
]
Interactive Python REPL with imports pre-loaded
python -i -c "import json, os, sys, pathlib; from pathlib import Path; print('Ready. Path, json, os, sys loaded.')"
Output:
Ready. Path, json, os, sys loaded.
>>>
How python -c and python -m differ
The -c flag runs the argument string as a tiny module; the -m flag runs an installed module as __main__. Both let you skip writing a .py file, but they hit different parts of the toolchain. Reach for -c for ad-hoc Python expressions; reach for -m for tools that already ship as modules (http.server, json.tool, timeit, pip, venv, unittest).
# -c: run an inline statement
python -c "print(2 ** 16)"
# -m: run a module
python -m json.tool < data.json
python -m http.server 8080
python -m timeit "sum(range(100))"
python -m venv .venv
python -m unittest test_module
Output:
65536
Multi-line
-cworks fine when you use real newlines inside double quotes:python -c "import sys$'\n'for line in sys.stdin: print(line.upper(), end='')"— but for anything past three lines, a heredoc (python - <<'PY' ... PY) is more readable than escaping inline.
Multi-line one-liners with heredocs
Most "one-liners" of any complexity are really short scripts run from a heredoc. The trick is the lonely - (read script from stdin) plus a quoted heredoc tag (<<'PY' — the quotes prevent shell expansion).
python - <<'PY'
import sys, json
data = {"now": __import__("datetime").datetime.utcnow().isoformat(),
"argv": sys.argv,
"pid": __import__("os").getpid()}
print(json.dumps(data, indent=2, default=str))
PY
Output:
{
"now": "2026-05-25T11:43:09.842321",
"argv": ["-"],
"pid": 48211
}
Pretty-print Python data with json.tool
json.tool is a stdlib pretty-printer accessible from the shell — python -m json.tool reads JSON from stdin (or a file) and writes formatted output. Use --sort-keys for stable diffs and --indent N to control width.
echo '{"b":1,"a":[3,2,1]}' | python -m json.tool --sort-keys --indent 2
Output:
{
"a": [
3,
2,
1
],
"b": 1
}
Filter a JSON document like jq
jq is the canonical tool, but if you don't have it, python -c plus json.load(sys.stdin) is a one-line fallback that runs anywhere Python does. Extract a nested key, filter records, or reshape a payload without leaving the shell.
# Extract a nested field
echo '{"user":{"name":"Alice","age":30}}' \
| python -c "import json,sys; print(json.load(sys.stdin)['user']['name'])"
# Filter a list by predicate
echo '[{"name":"Alice","age":30},{"name":"Bob","age":17}]' \
| python -c "import json,sys; [print(u['name']) for u in json.load(sys.stdin) if u['age']>=18]"
# Reshape — flatten to lines of key=value
echo '{"host":"myhost","port":8080,"tls":true}' \
| python -c "import json,sys; [print(f'{k}={v}') for k,v in json.load(sys.stdin).items()]"
# Pretty-print only specific keys
echo '{"a":1,"b":2,"c":3}' \
| python -c "import json,sys; d=json.load(sys.stdin); print(json.dumps({k:d[k] for k in ('a','c')}, indent=2))"
Output:
Alice
Alice
host=myhost
port=8080
tls=True
{
"a": 1,
"c": 3
}
For full
jq-equivalent power inside Python, installjq's Python binding (pip install jq) orglom(pip install glom) — both give you path expressions over nested dicts. For one-shot CLI use though, plain stdlib is enough.
YAML / TOML / CSV one-liners
For YAML and TOML you need a library (PyYAML or stdlib tomllib on 3.11+). CSV ships with the standard library.
# YAML → JSON
pip install pyyaml -q
cat config.yaml | python -c "import yaml,sys,json; print(json.dumps(yaml.safe_load(sys.stdin), indent=2))"
# TOML (Python 3.11+) → JSON
cat pyproject.toml | python -c "import tomllib,sys,json; print(json.dumps(tomllib.loads(sys.stdin.read()), indent=2))"
# CSV column extraction — print column 2 of a CSV
cat data.csv | python -c "import csv,sys; [print(r[1]) for r in csv.reader(sys.stdin) if r]"
# CSV → TSV
cat data.csv | python -c "import csv,sys; w=csv.writer(sys.stdout, delimiter='\t'); [w.writerow(r) for r in csv.reader(sys.stdin)]"
# CSV column average
cat data.csv | python -c "
import csv, statistics, sys
rows = list(csv.DictReader(sys.stdin))
print(statistics.mean(float(r['age']) for r in rows))
"
Pythonic regex from the shell
Drop into Python when grep -P is missing (macOS BSD grep) or when the substitution involves groups or look-arounds that POSIX sed can't express.
# Print lines matching pattern
cat /etc/hosts | python -c "import re,sys; [print(l, end='') for l in sys.stdin if re.search(r'^127', l)]"
# Extract all capture groups
echo "alice 30, bob 25" | python -c "
import re, sys
for m in re.finditer(r'(\w+)\s+(\d+)', sys.stdin.read()):
print(m.group(1), '=', m.group(2))
"
# Substitute with named groups
echo "alice@example.com" | python -c "
import re, sys
print(re.sub(r'(?P<u>\w+)@(?P<d>[\w.]+)', r'\g<u> AT \g<d>', sys.stdin.read()), end='')
"
Output:
127.0.0.1 localhost
127.0.1.1 myhost
alice = 30
bob = 25
alice AT example.com
Calculator and math
The Python REPL is the world's most-installed scientific calculator. For one-off math, -c is the fastest path.
# Plain arithmetic
python -c "print(2 ** 64)"
python -c "print(3.14159 * 5 ** 2)"
# Trig and logs
python -c "import math; print(math.degrees(math.atan2(1, 1)))"
python -c "import math; print(math.log2(1_000_000))"
# Floor division and remainder
python -c "print(divmod(100, 7))"
# Hex / oct / bin / int with base
python -c "print(hex(255), oct(8), bin(13))"
python -c "print(int('1010', 2), int('ff', 16))"
# Fractions and decimals (exact arithmetic)
python -c "from fractions import Fraction; print(Fraction(1,3) + Fraction(1,6))"
python -c "from decimal import Decimal; print(Decimal('0.1') + Decimal('0.2'))"
Output:
18446744073709551616
78.53975
45.0
19.931568569324174
(14, 2)
0xff 0o10 0b1101
10 255
1/2
0.3
Date and time
datetime, time, and zoneinfo (3.9+) cover almost every date one-liner you'll need. For ISO formatting use .isoformat(); for human-readable, use strftime.
# Now in different forms
python -c "from datetime import datetime; print(datetime.now().isoformat())"
python -c "from datetime import datetime; print(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S UTC'))"
# Today in a specific timezone (Python 3.9+ stdlib)
python -c "from datetime import datetime; from zoneinfo import ZoneInfo; print(datetime.now(ZoneInfo('Asia/Kolkata')).isoformat())"
# Parse a date and add days
python -c "from datetime import date, timedelta; print(date.fromisoformat('2026-01-01') + timedelta(days=120))"
# Days between two dates
python -c "from datetime import date; print((date(2026,12,31) - date.today()).days, 'days left')"
# Unix epoch seconds
python -c "import time; print(int(time.time()))"
python -c "from datetime import datetime; print(datetime.fromtimestamp(1700000000).isoformat())"
Output:
2026-05-25T11:43:09.842321
2026-05-25 06:13:09 UTC
2026-05-25T11:43:09.842321+05:30
2026-05-01
220 days left
1748167389
2023-11-14T19:43:20
Hashing — md5, sha1, sha256, blake2b
hashlib covers every common digest. To hash a file, read it in chunks to avoid loading huge files into memory.
# Hash a literal string
python -c "import hashlib; print(hashlib.md5(b'hello').hexdigest())"
python -c "import hashlib; print(hashlib.sha1(b'hello').hexdigest())"
python -c "import hashlib; print(hashlib.sha256(b'hello').hexdigest())"
python -c "import hashlib; print(hashlib.blake2b(b'hello', digest_size=16).hexdigest())"
# Hash a file (streaming)
python -c "
import hashlib, sys
h = hashlib.sha256()
with open(sys.argv[1], 'rb') as f:
for chunk in iter(lambda: f.read(8192), b''):
h.update(chunk)
print(h.hexdigest())
" /etc/hosts
# HMAC
python -c "import hmac, hashlib; print(hmac.new(b'secret', b'message', hashlib.sha256).hexdigest())"
Output:
5d41402abc4b2a76b9719d911017c592
aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
324dcf027dd4a30a932c441f365a25e8
File and directory one-liners
Pair python -c with pathlib for portable filesystem snippets that work on Windows, macOS, and Linux.
# Print absolute path of relative input
python -c "from pathlib import Path; import sys; print(Path(sys.argv[1]).resolve())" notes.txt
# List Python files under cwd, recursively
python -c "from pathlib import Path; [print(p) for p in sorted(Path('.').rglob('*.py'))]"
# Sum the size of all files in a directory
python -c "from pathlib import Path; print(sum(f.stat().st_size for f in Path('.').rglob('*') if f.is_file()), 'bytes')"
# Find the 5 largest files under cwd
python -c "
import heapq
from pathlib import Path
top = heapq.nlargest(5,
((p.stat().st_size, p) for p in Path('.').rglob('*') if p.is_file()),
key=lambda x: x[0])
for size, p in top: print(f'{size:>10} {p}')
"
# Touch a file (create or update mtime)
python -c "from pathlib import Path; Path('marker').touch()"
# Remove empty directories under cwd
python -c "
from pathlib import Path
for d in sorted(Path('.').rglob('*'), key=lambda p: -len(p.parts)):
if d.is_dir():
try: d.rmdir()
except OSError: pass
"
HTTP requests with the standard library
Even without requests, the stdlib (urllib.request, http.client) can fetch URLs in one line.
# GET a URL and print
python -c "import urllib.request; print(urllib.request.urlopen('https://httpbin.org/ip').read().decode())"
# Download a file (binary safe)
python -c "
import urllib.request, sys
urllib.request.urlretrieve(sys.argv[1], sys.argv[2])
" https://example.com/file.zip /tmp/file.zip
# POST JSON
python -c "
import json, urllib.request
body = json.dumps({'q': 'hello'}).encode()
req = urllib.request.Request('https://httpbin.org/post', data=body,
headers={'Content-Type': 'application/json'})
print(urllib.request.urlopen(req).read().decode())
"
# Send a header (User-Agent) and print response status
python -c "
import urllib.request
r = urllib.request.urlopen(urllib.request.Request('https://example.com',
headers={'User-Agent': 'mycli/1.0'}))
print(r.status, r.headers.get('Content-Type'))
"
The stdlib is fine for one-offs but lacks retries, connection pooling, and TLS verification toggles. For real applications, install
httpxorrequests.
Compression and archives
zipfile, tarfile, gzip, and bz2 cover archive creation, listing, and extraction from the shell.
# Create a ZIP from a directory
python -c "
import shutil, sys
shutil.make_archive(sys.argv[1], 'zip', sys.argv[2])
" backup ./src
# Extract a ZIP
python -c "import zipfile,sys; zipfile.ZipFile(sys.argv[1]).extractall(sys.argv[2])" archive.zip /tmp
# List ZIP contents
python -c "import zipfile,sys; [print(n) for n in zipfile.ZipFile(sys.argv[1]).namelist()]" archive.zip
# Gzip a single file
python -c "
import gzip, shutil, sys
with open(sys.argv[1], 'rb') as r, gzip.open(sys.argv[1] + '.gz', 'wb') as w:
shutil.copyfileobj(r, w)
" data.csv
# Tarball a folder
python -c "
import tarfile, sys
with tarfile.open(sys.argv[1] + '.tar.gz', 'w:gz') as t:
t.add(sys.argv[1])
" project
Encoding tricks
Beyond base64, the stdlib speaks hex, ROT13, quoted-printable, and many text encodings via codecs.
# Hex
python -c "print(b'hello'.hex())"
python -c "print(bytes.fromhex('68656c6c6f').decode())"
# ROT-13
python -c "import codecs; print(codecs.encode('Hello World', 'rot_13'))"
# Quoted-printable
python -c "import quopri; print(quopri.encodestring(b'naïve text').decode())"
# Detect encoding (best-effort)
python -c "
import chardet, sys
data = sys.stdin.buffer.read()
print(chardet.detect(data))
" < some_file
Counting, sorting, deduplicating — replace awk/sort/uniq
collections.Counter makes the common "count occurrences" pipeline a one-liner. For sort-by-value, sorted(..., reverse=True) over .most_common() is canonical.
# Word frequency in a file
cat /etc/hosts | python -c "
import sys, collections, re
words = re.findall(r'\w+', sys.stdin.read().lower())
for w, n in collections.Counter(words).most_common(10):
print(f'{n:>4} {w}')
"
# Deduplicate preserving order (set + filter)
printf "a\nb\na\nc\nb\n" | python -c "
import sys
seen = set()
for line in sys.stdin:
if line not in seen:
seen.add(line); sys.stdout.write(line)
"
# Sort numerically (real numeric, not lexicographic)
printf "10\n2\n30\n4\n" | python -c "import sys; [print(n) for n in sorted(int(l) for l in sys.stdin)]"
# Histogram
printf "a\nb\na\nc\nb\nb\n" | python -c "
import sys, collections
c = collections.Counter(l.strip() for l in sys.stdin)
m = max(c.values())
for k, v in c.most_common():
print(f'{k:>3} {\"█\"*v:<{m}} {v}')
"
Output (histogram example):
b ███ 3
a ██ 2
c █ 1
Permutations, combinations, products — itertools from the shell
Combinatorics one-liners are the cleanest demonstration of itertools. They're also surprisingly useful in scripting — generating test inputs, brute-force search spaces, or coverage matrices.
# All 2-letter permutations of ABC
python -c "from itertools import permutations; [print(''.join(p)) for p in permutations('ABC', 2)]"
# All 3-bit combinations
python -c "from itertools import product; [print(''.join(p)) for p in product('01', repeat=3)]"
# Cartesian product (each env × each region)
python -c "
from itertools import product
for env, region in product(['dev','staging','prod'], ['us-east','eu-west','ap-south']):
print(f'{env}/{region}')
"
# Pairwise (sliding window of 2) — 3.10+
python -c "from itertools import pairwise; [print(a, b) for a, b in pairwise([1,2,3,4,5])]"
# Group consecutive equal items
python -c "
from itertools import groupby
data = 'aaabbcaaaa'
for key, grp in groupby(data):
print(key, len(list(grp)))
"
Output:
AB
AC
BA
BC
CA
CB
a 3
b 2
c 1
a 4
See itertools & functools for the full set of combinator helpers — chain, accumulate, batched, compress, starmap, and the rest are all callable from a -c one-liner.
Comparison with awk, sed, jq, and xargs
Python one-liners compete directly with classic Unix tools — each has a sweet spot. The right tool depends on the input shape, the transformation, and how much portability you need.
| Task | Best tool | Python one-liner suffices when |
|---|---|---|
| Column extraction | awk (awk '{print $2}') | Columns are CSV/TSV and need real parsing |
| Stream substitution | sed | Substitution involves named groups or unicode |
| JSON path / filter | jq | jq isn't installed; payload fits in memory |
| Per-line transform | awk / sed | Logic exceeds 50 chars; need real types |
| Sort numerically | sort -n | You also need to compute or filter at the same time |
| Counting / histogram | sort | uniq -c | You want sorted output by frequency, not name |
| Pipe-fan parallel exec | xargs -P / parallel | You want type-checked arguments + retries |
| Time / date arithmetic | date -d (GNU) | Crossplatform: date -d syntax differs on BSD/macOS |
| Hashing | sha256sum | You need to combine hashing with parsing |
| Base64 | base64 | You need to chain with json/urlencoding/regex |
Rule of thumb: if the Unix tool exists and ships everywhere you care about, use it — it's faster and shorter. Reach for python -c when you need real types (dates, JSON, regex with named groups), portable behaviour across macOS and Linux, or composition that would take multiple piped Unix tools.
Common pitfalls
Quoting on Windows is different.
cmd.exestrips double quotes frompython -c "..."arguments in surprising ways. PowerShell handles it more cleanly. Preferpython -c '...'(single quotes) on macOS/Linux/PowerShell and reserve double quotes when you need shell variable interpolation.
python -c "print('x')"intowc -cand you get 2, not 1. Passend=""or write tosys.stdoutdirectly:python -c "import sys; sys.stdout.write('x')".
exec(open(f).read())is not the same as running a file. It runs in the current namespace, has weird__file__semantics, and won't catch syntax errors with a useful traceback. Preferpython myfile.pyorrunpy.run_path(...)for proper script invocation.
List comprehensions for side effects look "Pythonic" but aren't.
[print(x) for x in seq]builds a throwaway list ofNones. It works, but aforloop is clearer and avoids the false impression that you're collecting results. Use it sparingly in one-liners where brevity wins.
python -cruns in__main__, not a fresh interpreter setup. That means noif __name__ == "__main__"guard, no__file__, andsys.argv[0]is-c. Tools that depend on these (some logging configs, multiprocessing) misbehave.
open()withoutencoding=is locale-dependent. On Windows it might default to cp1252; on Linux to UTF-8. Always passencoding="utf-8"explicitly in cross-platform one-liners.
Real-world recipes
Find broken JSON files in a directory
Iterate every .json under cwd, try to parse each, and print only the ones that fail. Useful before re-running a batch ingest.
python - <<'PY'
import json
from pathlib import Path
for p in sorted(Path(".").rglob("*.json")):
try:
json.loads(p.read_text(encoding="utf-8"))
except Exception as e:
print(f"BROKEN {p}: {e}")
PY
Convert a directory of CSVs into one combined JSON
A common ETL one-liner — concatenate every .csv in data/ into a single JSON array, tagging each row with its source filename.
python - <<'PY'
import csv, json
from pathlib import Path
out = []
for p in sorted(Path("data").rglob("*.csv")):
with p.open(encoding="utf-8") as f:
for row in csv.DictReader(f):
row["__source__"] = p.name
out.append(row)
print(json.dumps(out, indent=2))
PY
Tiny HTTP API mock with http.server
http.server ships with the stdlib. Combine with a BaseHTTPRequestHandler subclass in a heredoc and you have a single-file mock API in under 20 lines — no Flask required.
python - <<'PY'
import json
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.end_headers()
self.wfile.write(json.dumps({"ok": True, "path": self.path}).encode())
print("listening on :8765")
ThreadingHTTPServer(("0.0.0.0", 8765), Handler).serve_forever()
PY
Rename a batch of files with a regex pattern
A safer replacement for rename (which varies wildly across distros). Always run the dry-run first.
python - <<'PY'
import re
from pathlib import Path
DRY = True
pattern = re.compile(r"^IMG_(\d{4})\.JPG$", re.IGNORECASE)
for p in sorted(Path(".").iterdir()):
m = pattern.match(p.name)
if not m: continue
target = p.with_name(f"photo_{m.group(1)}.jpg")
print(f"{'DRY ' if DRY else 'MV '}{p} -> {target}")
if not DRY:
p.rename(target)
PY
Read a .env file into the current shell
A Python alternative to set -a; source .env; set +a that handles quoting and comments correctly.
eval "$(python - <<'PY' .env
import sys, shlex
for raw in open(sys.argv[1]):
line = raw.strip()
if not line or line.startswith("#"): continue
if "=" not in line: continue
k, v = line.split("=", 1)
print(f"export {k.strip()}={shlex.quote(v.strip())}")
PY
)"
echo "$DATABASE_URL"