Subject: bug#33942: ls directly uses filename as option parameter

From: westlake <[email-masked]>
Date: Mon, 31 Dec 2018 21:52:28 -0500

Hi coreutils team,

  I have known long time about certain commands that use "--" as a 
specially reserved parameter. However, I find the behaviour of it with 
ls showing a little confusing results and believe this surmounts to a bug,

by example, ls exhibits unpredictable behaviour when there's also a file 
called "--".

it took me a bit of time today to look into after I revisited the 
problems of having "-" at the beginning of filenames, but decided with a 
little extra time into the holidays to look at it.. and found out that 
having a file called "./--" creates unpredictable behaviour.. cut to the 
chase, I pretty much summarize that the filename "./--" is definitely 
being consumed and utilized as a "program parameter" which is not a very 
sane thing for a program to do (so this is why I am filing this as a bug 
report here first rather than going directly with developers responsible 
for getopt)

$ mkdir tmp
$ cd tmp   (so we start with an empty folder)

$touch 0 ./--a ./-a ./-_a ./--

$ ls -lad  -* [^-]*
-rw-r--r-- 1 user user 0 Dec 31 18:37 0
-rw-r--r-- 1 user user 0 Dec 31 18:33 -_a
-rw-r--r-- 1 user user 0 Dec 31 18:34 --a

ls -lad  -* [^-]*
-rw-r--r-- 1 user user 0 Dec 31 18:37 0
-rw-r--r-- 1 user user 0 Dec 31 18:33 -_a
-rw-r--r-- 1 user user 0 Dec 31 18:34 --a

$ ls -lad --  -* [^-]*
-rw-r--r-- 1 user user 0 Dec 31 19:10 --
-rw-r--r-- 1 user user 0 Dec 31 18:37 0
-rw-r--r-- 1 user user 0 Dec 31 18:33 -_a
-rw-r--r-- 1 user user 0 Dec 31 18:34 --a

$ ls -lad -- *
-rw-r--r-- 1 user user 0 Dec 31 18:35 --
-rw-r--r-- 1 user user 0 Dec 31 18:37 0
-rw-r--r-- 1 user user 0 Dec 31 18:33 -_a
-rw-r--r-- 1 user user 0 Dec 31 18:34 --a

Notice that example 2, "-*" is being parsed with "--a" ,   is "./--" not 
showing up due to "design" or is this a "bug" ?  If "--a" is getting 
listed, then so should the file called "./--",

"$ ls -lad -- *"

  this command shows all files.

Delete file ./-- with "rm ./--", and now we try the command "ls -lad *", 
the output now is ls complains.

Okay I understand ls complaining:
"
ls -lad *
ls: invalid option -- '_'
Try 'ls --help' for more information.
"

^ but it is counter-intuitive because having a file called "./--", and 
this command passes.

If there is detectable filenames as the next example would show, then 
why can't "-*" list file ./--  ? Is this a bug or a design to comply 
with similar behaviour of ls on *nix?

See this example,
"
ls -lAd -- -* [^-]* --
"

Here the first instance of "--" is taken as a special option for ls, and 
the second "--" is being taken as a filename literal.  There is really 
only one file called ./-- , but here as expected it is intentionally 
being listed twice.

So here ls works as expected, but why I am mentioning this..
"
$ ls -* [^-]* -- -lad
ls: cannot access '-lad': No such file or directory
--  0  -_a  --a
"

Here we can see that ls is performing filenaming parsing after it 
detected filenaming arguments after the "-*" ,  evidently it is also 
taking "-lad" as a filename literal, and this is understood.

So essentially here we have "--" being taken as a filename literal, and 
ls uses this correctly.

Question: so why can't ls expand "-*" to "./--"  ? (fwiw, it does when 
using "ls -lad -- -*, and when using "--" as a special parameter)

What about file "---" or file "----" ?

These files show up properly,

$ touch ./--- ./----

$ ls -lAd -* [^-]*
-rw-r--r-- 1 user user 0 Dec 31 21:10 ---
-rw-r--r-- 1 user user 0 Dec 31 21:10 ----
-rw-r--r-- 1 user user 0 Dec 31 21:02 0
-rw-r--r-- 1 user user 0 Dec 31 21:02 -a
-rw-r--r-- 1 user user 0 Dec 31 21:02 -_a
-rw-r--r-- 1 user user 0 Dec 31 21:02 --a

^  file "./--" is missing, why? (getopt?)

I'm curious as to why ls would take the file "./--" and then use that as 
a "special parameter" rather than a regular file, and then on top of 
this completely omit it from output ( ls -lad * )... It uses it as a 
special parameter because it then does not fail with that message " ls: 
invalid option -- '_' " ...

I think it is a bug, because if something is read from disk, it should 
not directly be treated as a special parameter to ls, .. so this is why 
I am filing this.

thanks