34

I've tried

rm -- -
rm "-"
rm "\-"
rm \-

Gave Perl a shot

~$ perl -e '$junk = glob("-"); chomp $junk; print "$junk\n"; `rm $junk`;'
-
rm: cannot remove `-': No such file or directory

...and...

~$ perl -e '$junk = glob("-"); chomp $junk; print "$junk\n"; `mv $junk newfile.garbage`;'
-
mv: cannot stat `-': No such file or directory

Any assistance would be much appreciated, wise folks.

12 Answers12

61

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.

wallyk
  • 1,349
39

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).

19

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 {} \;
Sam
  • 191
13

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 ./-.

slhck
  • 235,242
Petey B
  • 696
7

Try:

$ ls -b

to see if the filename has unprintable characters.

Gareth
  • 19,080
Noel Yap
  • 181
7

Not as geeky as most other answers, but I would fire up an instance of mc, midnight commander, and just select and delete the file.

johanvdw
  • 171
6

Not that it should be necessary to use perl here, but this should work:

perl -e 'unlink "-"'

or to see what any error with the above might be:

perl -e 'unlink "-" or die "Err: $!"'
runrig
  • 161
3

I have had luck using GNOME's Nautilus to remove badly named files. Are you running an X-server? I'm sure other file browsers would work too.

3

If

rm -- -

didn't work, the file name is not "just a hyphen". If no other files have a hyphen in them, you could try

perl -E'for (@_) { if (/-/) { unlink($_) or die $! } }' -- *
ikegami
  • 234
1

So far I get a "No such file or directory" for every method posted so far:

rm ./-
rm -- -
mv "-" test.txt
rm -rf '-' <-- this gives no error, but doesn't work
perl -e 'unlink "-";'  <--also no error, doesn't work.

It appears I've got rm version 7.4. I'll try upgrading and re-attempting these suggestions. Thanks everyone for helping.

1

I'm very fond of using dired mode in emacs for this kind of thing -- just "open" the directory in emacs. You can easily select files and mark them for deletion.

Another poster suggested using midnight commander; this is pretty much the same idea, but if you're already an emacs user it's perhaps more convenient.

0

Should be able to do rm -f '-' worked for me in cygwin

For that matter, rm - also seems to work on red hat.

Lucas
  • 113