Skip to content

Instantly share code, notes, and snippets.

@Fordi
Last active September 30, 2026 19:56
Show Gist options
  • Select an option

  • Save Fordi/47bade5d63d4a6cb72c4b9df8e5185d1 to your computer and use it in GitHub Desktop.

Select an option

Save Fordi/47bade5d63d4a6cb72c4b9df8e5185d1 to your computer and use it in GitHub Desktop.
Sourceable script to add `-i` / `--in-place` option to `jq`
#!/bin/bash
# Add in-place editing support to `jq`
# `source` it in your profile to wrap around `jq`, or run it directly
JQ="${JQ:-"$(command -v jq)"}"
function jq() {
# Original command line, minus -i/--in-place, in its original order
local passthrough=()
local positionals=()
local inplace=
local help=
local hasFromFile=
local suppressRemainder=
local arg
local original=("${@}")
while [[ $# -gt 0 ]]; do
arg="${1}"
shift
case "${arg}" in
-i|--in-place)
inplace=true;;
-h|--help)
help=true;;
# Options that consume the following two arguments
--arg|--argjson|--slurpfile|--rawfile)
passthrough+=("${arg}" "${1}" "${2}")
shift 2 || break;;
# Options that consume the following argument
-f|--from-file)
hasFromFile=true
passthrough+=("${arg}" "${1}")
shift || break;;
--indent|-L)
passthrough+=("${arg}" "${1}")
shift || break;;
# Everything after these is an argument for the filter, not a file
--args|--jsonargs)
suppressRemainder=true
passthrough+=("${arg}");;
-*)
passthrough+=("${arg}");;
*)
passthrough+=("${arg}")
if [[ -z "${suppressRemainder}" ]]; then
positionals+=("${arg}")
fi;;
esac
done
# Inform the user of the new flag
if [[ -n "${help}" ]]; then
"${JQ}" --help | sed '/--null-input/a\ -i, --in-place update the file in-place;' || true
return
fi
# If inplace wasn't flagged, just run JQ as normal
if [[ -z "${inplace}" ]]; then
"${JQ}" "${original[@]}"
return $?
fi
# With -f, every positional is a file; otherwise the first is the filter.
local files=("${positionals[@]}")
if [[ -z "${hasFromFile}" ]]; then
files=("${positionals[@]:1}")
fi
if [[ ${#files[@]} -ne 1 ]]; then
echo "--in-place requires exactly one input file" >&2
return 1
fi
local file="${files[0]}"
local tmp ret
tmp="$(mktemp)"
rm -f "${tmp}"
cp -dP "${file}" "${tmp}"
"${JQ}" "${passthrough[@]}" > "${tmp}"
ret=$?
if [[ "${ret}" == "0" ]]; then
mv "${tmp}" "${file}"
else
echo "Error: jq failed; \`${file}\` not modified" >&2
rm -f "${tmp}"
return "${ret}"
fi
}
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
jq "${@}"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment