Because it’s fun, here’s an alternative spelling of `echo .dump | sqlite3`:<p><pre><code> <<<.dump sqlite3
</code></pre>
This avoids invoking echo unnecessarily. Every time you do it you might just save a picowatt-hour or two! (It <i>shouldn’t</i> be more expensive. But be sure to spend a few watt-hours benchmarking it rigorously.)<p>This uses two things that shell users are commonly unfamiliar with:<p>• <<<: as `> filename` redirects stdout to the named file and `< filename` pipes the named file into stdin, `<<< word` pipes the word into stdin. (The whitespace is optional, and word follows normal argument splitting so you can do things like `<<<"Hello, world!"`.)<p>• Ordering: although most commonly written at the end of commands, redirections can be placed at the start as well. So if you do things like `2>/dev/null >&2` to suppress all output¹, that bit can go at the start or the end. I’ve become increasingly partial to putting redirections at the start of the line, especially in cases where I’m appending to a file for a while, because a leading `>>filename` supports visual alignment better than a trailing.²<p>And since we’re talking about different ways: as given, this is feeding the SQL to sqlite3 via stdin, but you can also pass it on the command line, after the filename. But things like this in Git (aliases, diff textconv, probably more) work by taking the string and appending the filename to the end, so you need a way of reordering the arguments. The solution is an immediately-invoked function:<p><pre><code> f() { sqlite3 "$@" .dump; }; f
</code></pre>
So when you diff mydb.sqlite, it runs `sh -c 'f() { sqlite3 "$@" .dump }; f mydb.sqlite'` or equivalent, which winds up executing `sqlite3 mydb.sqlite .dump`, as desired.<p>I use this technique a number of times in my Git aliases, saving the bother of putting them in separate shell scripts somewhere where path management is a bother, at the cost of maintaining a one-liner with sometimes too many semicolons.³<p>—⁂—<p>¹ “Take stderr (2) and redirect it (>) to /dev/null, then take stdout (default/implicit, could also write 1 explicitly) and redirect it (>) to stderr (&2).” There are plenty of other ways of writing this!<p>² Lists can be a better solution for this specific case, allowing you to redirect to the file only once for a whole bunch of commands:<p><pre><code> {
<<<"Line one"
some-command
<<<"End of $thing"
} > filename
</code></pre>
³ My longest is thirteen lines, though half of them barely count as <i>lines</i>. The line from my ~/.config/git/config, within [alias]:<p><pre><code> # Revise into the commit that last changed File
rf = "!f() { if [ $# -eq 0 ]; then REV=\"$(git status --porcelain --untracked-files=no | sed '/^ /d;s/^.. //' | xargs -n1 git rev-list -1 HEAD -- | uniq)\"; NUM_REVS=\"$(echo \"$REV\" | wc -l)\"; if [ $NUM_REVS -ne 1 ]; then >&2 echo Files in the index were not all last modified in the same commit; exit 1; fi; else REV=\"$(git rev-list -1 HEAD -- \"$1\")\"; shift; fi; git revise \"$REV\" \"$@\"; }; f"</code></pre>