How do I remove a file in Linux whose name looks like it's ONLY a hyphen, as in "-"

This used to be posted in the Usenet FAQs for Unix—I see it is in the GNU Core Utility FAQs. There were at least five different methods, but this works well:

$ rm ./-

If a filename contains untypeable characters, then use:

$ rm -i *

The -i flag asks for confirmation for each file if it should be removed or not.


Removing a file whose names starts with - is a FAQ, but it looks like you've got a different problem.

Of the solutions you mentioned in the question:

rm -- -

That should work.

rm "-"

That's no different from rm -. The quotes are stripped by the shell, and the rm command just sees the single hyphen as an argument. Quotation marks are useful for escaping shell metacharacters; the hyphen is special to rm, not to the shell.

rm "\-"

The quotation marks escape the backslash, so this attempts to remove a file whose name consists of two characters, a backslash and a hyphen.

rm \-

This is just like rm "-", equivalent to rm -.

As it happens, at least with the GNU coreutils version of rm, rm - actually removes (or attempts to remove) a file whose name consists of just a hyphen. If your file had that name, it would be gone by now. I conclude that your file has a name that only looks like a hyphen.

ls | cat -A

should give an idea of what it's really called.

Here's a Perl script I just threw together that will prompt you for each file in the current directory and ask whether to remove it. Offered without warranty, but I've tested it briefly.

#!/usr/bin/perl

use strict;
use warnings;

$| = 1;

opendir my $DIR, '.' or die ".: $!\n";
my @files = sort grep { -f $_ } readdir $DIR;
closedir $DIR;

foreach my $file (@files) {
    print "Remove $file? ";
    my $answer = scalar <>;
    if ($answer =~ /^[Yy]/) {
        unlink $file or warn "$file: $!\n";
    }
    elsif ($answer =~ /^[Qq]/) {
        exit 0;
    }
}

EDIT: A less elaborate solution: if the file's name is just one character, then rm ? should remove it (along with any other such files).


If you want something safer...

Try using a combination of ls and find (this works for any file you have permission to remove)

The '-i' parameter will give you the inode number for each directory entry ls -li

27 ----------  1 owner  group       3981 Oct 11 04:42 ?????

Once you have the inode number...

find . -inum **27** -exec rm -i {} \;

Give rm ./- a try.

The - is a flag to start a flag argument. If you start the argument with anything but a -, in this case /, it will assume it's the file name. Which is what you wish.

And since file and ./file are the same file, it will target the file named - via ./-.