Earlier this week something in my development environment, relating to Homebrew, Python, pyenv and pipenv, got updated and broke a handful of repositories. Not in a way that I couldn’t recover from, just in a way that was annoying, got in the way of my workflow, and needed attention. (note to self: how I set up for Python/Django development on a machine might be a good post in the future)
Once I was sure what the fix was (pretty much: nuke the virtual environment
and recreate it with
pipenv, being very explicit about the version of
Python to use) the next step was to figure out how many repositories were
affected; not all were and there wasn’t an obvious pattern to it. What was
obvious was that the problem came down to
python in the
pointing to a binary that didn’t exist any more.
So… tracking down problematic repositories would be simple enough, just
look for every instance of
.venv/bin/python and be sure it points to
something rather than nothing; if it points to nothing I need to remake the
I quickly knocked up a script that was based around looking over the results
find, and initially decided to use
file to perform the test on
python. It seemed to make sense, as I wrote the script I checked the
file(1) on macOS and sure enough, this exists:
-E On filesystem errors (file not found etc), instead of handling the error as regular output as POSIX mandates and keep going, issue an error message and exit.
file dereferences links by default, that should get me an error
for a broken link, right? Bit hacky I guess, but it was the first thing that
came to mind for a quick bit of scripting and would do the trick. Only…
$ file -E does-not-exist file: invalid option -- E Usage: file [bcCdEhikLlNnprsvzZ0] [-e test] [-f namefile] [-F separator] [-m magicfiles] [-M magicfiles] file... file -C -m magicfiles Try `file --help' for more information.
Wat?!? But it’s right there! It says so in the manual!
-E is documented right in the manual page! And yet it’s not in the valid switch list as put out by the command, and it’s an
invalid option. The hell?
So I go back and look at the
man page again and then I notice it isn’t in
the list of switches in the synopsis.
file [-bcdDhiIkLnNprsvz] [–extension] [–mime-encoding] [–mime-type] [-f namefile] [-m magicfiles] [-P name=value] [-M magicfiles] file
file -C [-m magicfiles]
I then did the obvious tests. Did I have
file aliased in some way? No. Was
some other thing that works and acts like
file in my path? No. Was I
absolutely 100% using
Long story short: it seems the
man page for
file, on macOS, fibs about
what switches it supports; it says that
-E is a valid option, but it’s not
What’s even odder is the man page says it documents v5.04 of the command,
--version reports v5.37. Meanwhile, if I check on a GNU/Linux box I
have access to, it does support
-E, reports it in the switches, documents
it in the
man page (in both the synopsis and in the main body of the page)
and it is v5.25 (and so is its man page).
So that was something like 20 minutes lost to a very small problem, for which there was no real solution, but was time that had to be spent to get to the bottom of it.
In the end I went with what I probably should have gone with in the first
for venv in $(find . -name .venv) do if ! stat -L "$venv/bin/python" > /dev/null 2>&1 then echo "$(dirname $venv)" fi done
And now I have that script in my
~/bin directory, ready for the next time
Homebrew and friends conspire to throw my day off for a while.