An interesting issue with the *nix ls command, or, why you should never begin a filename with a hyphen

In which I discover an odd error using ls and learn how to solve it.

The problem

I was just trying to list a series of files with a specific extension in a directory using the *nix ls command:

ls *.pdf

What I got back was an error:

ls: invalid option -- 'e'
Try 'ls --help' for more information.

What’s going on?

So where is the -e or --e option coming from?

Turns out, it is coming from a file-name that begins with - (in my case -Receipt- 4955-0.pdf). Apparently what is going on is that the filename is being read by ls as a set of options (in this case -Re, meaning “Recursive + [unknown option]”), and since there is no -e option in ls it is throwing an error. Pretty unexpected behaviour (I discovered this from this site).

The solution(s)

Don’t begin file names with -

The first (future) solution is never to begin file names with a hyphen. This is not something I normally do, though I read that some people do it in order to ensure that a file sorts at the top in a directory (if you are going to do that, better might be to use _, since that isn’t used as a control or meta character).

Explicitly end your options (“unset positional parameters”) before giving the file name

If you are running into this problem, then the first solution is too late for you, because you already have a file name beginning with a hyphen. So how do you prevent ls from reading the filename as an option?

The answer seems to be to use the -- option to “unset positional parameters.” That is, ending your list of options with -- tells bash that anything after the double hyphen is an argument rather than an option.

So in this case, I did the following:

ls -halt -- *.pdf

-halt are the options that I did want to have apply (Human readable, all files, long form listing [i.e. with all information about times and ownership], and sorted descending by date and time). Then -- “unsets the positional parameters” and *.pdf is a regular expression saying I’m looking only for files with the extension .pdf.

I’m thinking this might be good practice generally in bash scripting, since you sure don’t want a command like rm (remove) running wild if it hits a file with a name like -Receipt- 4955-0.pdf which might cause it to suddenly work recursively.

Bonus solution: How did you discover the offending file?

I had a lot of files in my directory, and only one of them began with a hyphen. How did I find it?

ls -- -*

Talk about compact!

tags: , , , , ,


Get every new post delivered to your Inbox

Join other followers: