2016-03-07
Why it makes sense for true
and false
to ignore their arguments
It's standard when writing Unix command line programs to make them check their arguments and complain if the usage is incorrect. It's reasonably common to do this even for programs that don't take options or positional arguments. After all, if your command is supposed to take no arguments, it's really an error if someone runs it and gives it arguments.
(Not all scripts, programs, and so on actually check this, because you usually have to go at least a little bit out of your way to look at the argument count. But it's the kind of minor nit you might get code review comments about, or an issue report.)
true
and false
are an exception to this, in that they more or
less completely ignore any arguments given to them. Part of this
behavior is historical; the V7 /bin/true
and /bin/false
were
extremely minimal, and when you're being minimal it's easiest to
not even look at the arguments. But beyond the history, I think
that this is perfectly sensible behavior for true
and false
because it makes them universal substitutes for other commands,
for when you want to null out a command so that it does nothing.
Want to make a command do nothing but always succeed? Simple: 'mv
command command.real; ln -s /bin/true command
'. Want to do the
same thing but have the command always fail? Use false
instead
of true
. Sure, you can do the same thing with shell scripts that
deliberately ignore the arguments and just do 'exit 0
' or 'exit
1
', but this is a little bit simpler and matches the historical
behavior.
(You can also do this in shell scripts as a way of creating a 'don't actually do anything' mode, but there are probably better patterns there.)
On that note, it's interesting to note that although GNU true
and
false
have command line options that will cause them to produce
output, there is no way to get them to return the wrong exit status.
And while they respond to --help
and --version
, they silently
ignore other options (as opposed to, say, reporting a syntax error).
(This entry was sparked by Zev Weiss's mention of true
in his
comment on this entry.)
Sidebar: true
and false
in V7
In V7 Unix, true
is an empty file and false
is a file that is
literally just 'exit 1
'. Neither has a #!
line at the start of
the file, because that came in later. That
true
is empty instead of 'exit 0
' saves V7 a disk block, which
probably mattered back then.
Apt-get and its irritating lack of easy selective upgrades
One of my many irritations with apt-get
is that it doesn't easily allow you to only apply some of the pending
updates. Sure, often you want to apply all of the updates (at
least all of the unheld updates), but there
are any number of cases where you want to be more selective. Sometimes
you are in a rush and you want to apply only a few very urgent
updates. Sometimes you want to apply updates in a specific order,
updating some packages before others. Sometimes you want to apply
most updates but temporarily exclude some that you consider low
priority or disruptive.
With a package manager like yum
(or now dnf
) you can easily do
either of these. If you just want to exclude some packages, you do
that with '--exclude
'; if you only want to upgrade some packages,
you do that by supplying them as explicit arguments. And it's
harmless to be a bit broad in your explicit arguments, because
you're specifically only upgrading existing packages; you'll never
install new ones out of nowhere.
apt-get
does not support this usage as far as I can see. apt-get
upgrade
takes no package list and has no way of excluding some
packages; it is an all or nothing operation, where the only way you
have of being selective is to hold packages in advance in order to
block their upgrades. In order to upgrade packages selectively, you
must turn to 'apt-get install
', probably with '--only-upgrade
'
so that you don't accidentally install new packages. And as far as
I can tell this has no equivalent of yum's --exclude
, so there's
no easy way I can see of saying 'upgrade everything except the
following packages'.
(apt-get install
does at least support wildcards, or more exactly
POSIX regular expressions. I don't know why they decided to use
regular expressions instead of shell globbing, but it feels like a
very Debian decision, especially the detail that it defaults to
matching substrings.)
'apt-get install --only-upgrade PKG ...
' solves about half of the
problem (although clumsily) so I'm less disgruntled than I was at
the start of writing this entry, but it's still not particularly
great.