I accidentally ran less
with an empty filename, which I expected to fail, but to my surprise, it printed some environment variables:
$ less -XE ""
export LESSOPEN="| /usr/bin/lesspipe %s";
export LESSCLOSE="/usr/bin/lesspipe %s %s";
(-XE
basically makes it behave like cat
.)
cat
, on the other hand, fails:
$ cat ""
cat: '': No such file or directory
And if you leave out the filename entirely, less
does error:
$ less -XE
Missing filename ("less --help" for help)
Why does less
do this? I can only imagine it being problematic, because if there's some bug in your code that causes an empty filename, you'll get bogus output. (Like, say, less "$(which nonexistent-script)"
.)
While we're here, why does it print those environment variables? Are they from my environment? They're identical:
$ declare -p LESSOPEN LESSCLOSE
declare -x LESSOPEN="| /usr/bin/lesspipe %s"
declare -x LESSCLOSE="/usr/bin/lesspipe %s %s"
I checked man less
but the filename parameter doesn't seem to be documented explicitly. Other mentions of it didn't seem to be related to this behaviour. I also checked the less
FAQ.
The root problem is that
less
doesn't properly quote the filename it's passing to theLESSOPEN
command: what it does is "Insert a backslash before each metacharacter", so that means it doesn't handle null strings at all. You can see it works as expected if you bypassLESSOPEN
:On Ubuntu (plus Debian, I believe), by default,
LESSOPEN
is configured by runninglesspipe
with no arguments, which prints the necessary environment variables to set itself as theLESSOPEN
handler. See Can you explain eval expression in the default .bashrc. So when runningless
with a null argument, the improper quoting deletes the argument being passed tolesspipe
, andlesspipe
prints its config.P.S.
I considered opening a bug against
less
, but this hasn't been a big problem for me. If anyone wants to take the initiative, by all means, and let me know if you need anything. One possible solution (but not backwards compatible) is thatless
wouldn't try to quote the filename at all, instead the filename would need to be quoted in the config, likeLESSOPEN='| /usr/bin/lesspipe "%s"'
.It might also be a good idea to open a bug against
lesspipe
to recommend a more verbose configuration usage.