objectif
Éviter de vider un fichier quand on lit et écrit en même temps depuis un pipeline. sponge (moreutils) absorbe toute l’entrée puis écrit le résultat en une seule fois, pratique pour sort, grep, jq, etc., même sur des fichiers système avec sudo.
code minimal
# dédupliquer et trier un fichier en l'écrivant "en place"
sort -u hosts.txt | sponge hosts.txt
utilisation
# reformater un JSON proprement (indentation stable)
jq . config.json | sponge config.json
# filtrer des lignes (supprimer les commentaires et vides)
grep -Ev '^\s*(#|$)' app.env | sponge app.env
# normaliser un fichier .gitignore (trier, dédupliquer, retirer vides)
grep -Ev '^\s*$' .gitignore | sort -u | sponge .gitignore
# appliquer un sed portable sans -i (BSD/GNU diffèrent)
sed 's/DEBUG=true/DEBUG=false/' .env | sponge .env
# mise à jour d'un vhost nginx de data.pm avec privilèges
sudo sh -c 'generate_nginx | sponge /etc/nginx/sites-available/data.pm.conf'
# ou directement si la commande produit la conf:
nginx -T | grep -A3 'server_name data.pm' | sudo sponge /etc/nginx/inspect.conf
# harmoniser des ACL (ex: allowlist) et réécrire
awk '{$1=tolower($1)}1' allowlist.txt | sort -u | sponge allowlist.txt
# nettoyer des logs de dev (garder les 10k dernières lignes)
tail -n 10000 app.log | sponge app.log
variante(s) utile(s)
# réécrire plusieurs fichiers (boucle sûre)
for f in *.md; do
awk 'NF' "$f" | sponge "$f"
done
# utiliser sponge derrière une commande qui peut échouer (fail-fast)
set -euo pipefail
( jq '.feature_flags |= keys|length' config.json || exit 1 ) | sponge config.json
# fallback sans sponge (portable): tmp + rename (non root)
tmp="$(mktemp)"; jq . config.json > "$tmp" && mv -f "$tmp" config.json
# fallback root (sudo) sans sponge: tmp + mv atomique
tmp="$(mktemp)"; jq . /etc/app.conf > "$tmp" && sudo mv -f "$tmp" /etc/app.conf
# protéger les permissions (réappliquer mode et propriétaire après réécriture)
mode="$(stat -c '%a' app.env 2>/dev/null || stat -f '%Lp' app.env)"
owner="$(stat -c '%u:%g' app.env 2>/dev/null || stat -f '%u:%g' app.env)"
grep -Ev '^\s*(#|$)' app.env | sponge app.env
chown "$owner" app.env 2>/dev/null || true
chmod "$mode" app.env 2>/dev/null || true
notes
spongelit tout le flux avant d’écrire, évitant quecat fichier | ... > fichiervide le fichier en amont.- utile quand
-ides outils varie selon les plateformes (ex:sed -iBSD vs GNU). Avecsponge, pas de différence. - pour écrire des fichiers système, placez
sudodu côté écriture:... | sudo sponge /chemin/fichier. spongen’assure pas une écriture “atomique” ni la préservation des permissions. Pour un besoin strict, utilisez un fluxtmp + mv(voir snippet “écriture atomique de fichier avec fsync”).- installez
moreutilspour disposer desponge(Debian/Ubuntu:sudo apt install moreutils, macOS:brew install moreutils).