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 -
[!TIP] 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
[!TIP] 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
}
[!TIP] 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'))
"
[!TIP] 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#
[!WARNING] 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.
[!WARNING]
python -c "print('x')"intowc -cand you get 2, not 1. Passend=""or write tosys.stdoutdirectly:python -c "import sys; sys.stdout.write('x')".
[!WARNING]
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.
[!WARNING] 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.
[!WARNING]
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.
[!WARNING]
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"