17

I accidentally created a file with the name - (eg, seq 10 > -). Then I tried to use less to view it, but it just hangs.

I understand that this is happening because less - expects input from stdin, so it does not interpret the - as a file name. I tried less \- but it does not work either.

So, is there any way to indicate less that - is a file and not stdin?

The best I could get is:

find -name '-' -exec less {} +
  • 2
    @muru thanks for the comment, but the possible duplicate is so specific that I don't think it qualifies to be "exact duplicate". If it was reworded to something more generic like "how to access a file beginning with '-'", maybe. – fedorqui Jun 17 '15 at 9:29
  • 4
    That's not a duplicate question. The case for - alone is different. - is not an option. – Stéphane Chazelas Jun 17 '15 at 10:35
  • 1
    @terdon I don't think that having the same answer directly means they are duplicates. There was an example somewhere in Meta SO: if a question gets answered with "No", would anything whose correct answer is "No" be a duplicate? As I said before, it would be interesting to reword the candidate of duplicate so that it is more generic; otherwise, it doesn't make much sense to send there other questions like this one. – fedorqui Jun 17 '15 at 11:23
  • 4
    @terdon, no. The accepted solution there won't work here. And no, - is not treated as an option, that's a totally different problem from the case of arguments that happen to be shaped like options. – Stéphane Chazelas Jun 17 '15 at 11:34
  • 2
    It is not necessary to enclose - between single quotes like '-' or escape it like \- because - is not a special character for common shells (at least POSIX compliant ones). The result is the same. – pabouk Jun 17 '15 at 12:06
53

Just prefix it with ./:

less ./-

Or use redirection:

less < -

Note that since - (as opposed to -x or --foo-- for instance) is considered a special filename rather than an option, the following doesn't work:

less -- -   # THIS DOES NOT WORK
  • 3
    BTW, that's what find -name '-' -exec less {} + runs. – Stéphane Chazelas Jun 17 '15 at 9:22
  • 6
    @fedorqui, no it's just that - and ./- (or /path/to/- or ../to/-) are two (4) valid paths to that - file, but a - argument is special to less (means read from stdin) while ./- is not special. – Stéphane Chazelas Jun 17 '15 at 9:26
  • 2
    @fedorqui find -name '-' -exec less {} + is the non-standard form for find . -name '-' -exec less {} +. It descends the tree at . and finds files and passes the paths of those files as arguments to less. Replace -exec less with -exec echo less to see what is being run. – Stéphane Chazelas Jun 17 '15 at 9:29
  • 4
    @haylem, -- is to mark the end of options. It won't help here. That - is not an option, it's a special non-option argument. See also unix.stackexchange.com/a/56370, unix.stackexchange.com/a/110756 – Stéphane Chazelas Jun 17 '15 at 10:16
  • 3
    @haylem, try it for yourself. -- is handled by getopt() to mark the end of options, - is not recognised as an option by getopt(), so that - will be recognised as a normal argument whether -- is provided or not. And as a normal argument, less like most text utilities will treat it as meaning stdin, which we don't want here. – Stéphane Chazelas Jun 17 '15 at 11:32
3

I would just mv - f && less f. Problem solved.

3

Note: my answer is NOT valid in the OP's case, and only applies to tools following the convention mentioned below and not in the case of a file named exactly just - (dash), which is often also a special case to specify that reading from standard input is expected. See the accepted answer.

Leaving this here as it contains useful information for other cases that one may stumble upon while searching for answers.


Double-Dash it!

Use the standard double-dash (--) convention to indicate the last argument:

less -- -FILENAME

Example

$ echo "meh" > -badname
$ less -badname
Number is required after -b
$ less -- -badname # GREAT SUCCESS!

Whhhaattt?

This -- argument stems from a convention supported by most implementations of shell utilities and command-line tools, and most shells will visibly advocate that you should follow it when implemeing CLI tools.

Recommdended by the Open Group

The OpenGroup also mentions it in the Utility description defaults (v6) section of its Base Specification:

Default Behavior: [...] Standard utilities that do not accept options, but that do accept operands, shall recognize "--" as a first argument to be discarded.

The requirement for recognizing "--" is because conforming applications need a way to shield their operands from any arbitrary options that the implementation may provide as an extension. For example, if the standard utility foo is listed as taking no options, and the application needed to give it a pathname with a leading hyphen, it could safely do it as:

foo -- -myfile

and avoid any problems with -m used as an extension.

And in the Utility Syntax Guidelines (v7):

Guideline 10: The first -- argument that is not an option-argument should be accepted as a delimiter indicating the end of options. Any following arguments should be treated as operands, even if they begin with the '-' character.

Recommended by Bash

Here, excerpted from the bash manual, about its builtins supporting it:

Unless otherwise noted, each builtin command documented in this section as accepting options preceded by - accepts -- to signify the end of the options.

The :, true, false, and test builtins do not accept options and do not treat -- specially. The exit, logout, break, continue, let, and shift builtins accept and process arguments beginning with - without requiring --. Other builtins that accept arguments but are not specified as accepting options interpret arguments beginning with - as invalid options and require -- to prevent this interpretation.

Note that echo does not interpret -- to mean the end of options.

Additional Reading

  • 2
    +1 : Most portable and command-independant solution, easy to remember, and considered the "best practice" – mveroone Jun 17 '15 at 9:32
  • 2
    @Kwaio any reference about the "best practice"? Just feel curious about it. – fedorqui Jun 17 '15 at 9:33
  • 24
    That answer applies to arguments that look like options. It's not the case for - which is not an option. Using ./- or redirection when possible is generally a better approach as it avoids other kinds of problems like the foo=bar of awk or that -. See also unix.stackexchange.com/a/56370, unix.stackexchange.com/a/110756 – Stéphane Chazelas Jun 17 '15 at 10:22
  • 7
    As Stéphane says, this does not answer the question. less -- - will still try to read from stdin. – Michał Politowski Jun 17 '15 at 11:11
  • 5
    You may want to delete the answer (or move it to the other question as there are useful references in here) or make it clear that it doesn't apply to this particular case (and maybe explain why which would be even more useful). – Stéphane Chazelas Jun 17 '15 at 11:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.