moreutils
has previously been covered elsewhere, multiple times. It’s a collection of small unix tools that follow the unix philosophy1 very strongly.
Here are some of my favorites with example usages. Obviously this post isn’t a manual which would have been a disservice to the community; refer to the upstream man pages for detailed instructions.
sponge
sponge(1) - soak up standard input and write to a file
Here’s a typical workflow sponge(1)
is great at:
# Given a file
$ cat myfile
a
b
c
# Imagine that for whatever reason we want to replace 'a' with 'b'
# Naively, we could try this:
$ cat myfile | tr 'a' 'b' > myfile
$ cat myfile
# However the file becomes empty!
# It got clobbered when we tried to simultenaously read from and write to it
# sponge comes to the rescue!
$ cat myfile | tr 'a' 'b' | sponge myfile
$ cat myfile
b
b
c
It is great to use sponge
in lieu of >
(shell output redirection) in shell pipelines when trying to both read from and write to the same file.
vidir
vidir(1) - edit directories and filenames
vidir(1)
is great to bulk rename files/directories within a given directory, one level at a time. For example, if I open vidir
at the top-level directory of this blog repository, it opens up vim
(although it doesn’t need to be vim
, your $EDITOR
is honoured) with the following content:
1 ./.git
2 ./.github
3 ./.gitignore
4 ./.gitmodules
5 ./.hugo_build.lock
6 ./LICENSE
7 ./Makefile
8 ./README.md
9 ./archetypes
10 ./config.yml
11 ./content
12 ./layouts
13 ./public
14 ./resources
15 ./static
16 ./themes
If I make, say, the following modifications (lines 7 and 8):
1 ./.git
2 ./.github
3 ./.gitignore
4 ./.gitmodules
5 ./.hugo_build.lock
6 ./LICENSE
7 ./GNUMakefile
8 ./README.rst
9 ./archetypes
10 ./config.yml
11 ./content
12 ./layouts
13 ./public
14 ./resources
15 ./static
16 ./themes
And then save and quit vim
(:wq
), then the effect would have been the same as:
$ mv Makefile GNUMakefile
$ mv README.md README.rst
If I changed my mind and decided not to save the modifications, I could just do :cq
.
It’s possible to leverage vim features such as .
(repeat command) and :%s/
(find and replace) to perform those mass file renames quickly and effectively. vidir
is a breeze to use!
ifne
ifne(1) - Run command if the standard input is not empty
ifne(1)
is effective when used with find
or fd
to keep shell pipes “happy”. Here’s one simple example:
$ find . -name '*.cpp' | xargs clang-format
This should work as expected, but it’s cleaner to do:
$ find . -name '*.cpp' | ifne xargs clang-format
The added ifne
ensures the xargs
command is only executed if and only if find
yields at least one result in its output.
This wasn’t a very practical example though: a more realistic way to use ifne
is with prototypical on-the-fly manipulation of shell pipes wherein initially you just do whatever, but then whenever you notice some command in the middle of the pipe has failed because its input was empty (=the previous pipe command output was empty) you just prepend ifne
to it:
$ this | is | a | complicated | pipe
# assume "complicated" fails because it has no input
# so we iterate and do:
$ this | is | a | ifne complicated | pipe
combine
combine(1) - combine sets of lines from two files using boolean operations
combine(1)
is pretty much comm(1)
, but much more user-friendly. Given two files file1
and file2
it makes it easy to query which lines are {unique, common} to {each, both} files, using boolean operations (or, and, not, xor). Here’s one example to find the common lines in both files, compare combine
and comm
:
$ combine file1 and file2
$ comm -12 file1 file2 # flags are harder to remember
The Unix philosophy emphasizes building simple, short, clear, modular, and extensible code that can be easily maintained and repurposed by developers other than its creators. The Unix philosophy favors composability as opposed to monolithic design. ↩︎