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.

9
  • Out of curiousity, how did it get there?
    – Petey B
    Oct 17, 2011 at 17:09
  • 2
    It was the result of a poorly constructed wget: "wget -q -O – someserver.org/s/ip"
    – user999624
    Oct 17, 2011 at 17:10
  • 53
    Reminds me of the time a colleague created a file named * . This story did not end well. Oct 17, 2011 at 17:14
  • What rm version are you using (rm --version)? rm - works fine with GNU coreutils 8.5.
    – Lekensteyn
    Oct 17, 2011 at 17:59
  • 2
    Another variant: rm ./-
    – user
    Oct 18, 2011 at 6:35

12 Answers 12

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.

2
  • 1
    Or rm -i -- '-' if you are looking for files containing a dash and maybe some spaces or whatever. Oct 21, 2011 at 6:19
  • 2
    rm -i * also worked for me. Thanks wallyk!
    – jgrundstad
    Oct 25, 2011 at 16:04
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).

12
  • 13
    M-bM-^@M-^S is a rendition of the 3-byte UTF-8 representation of the Unicode "EN DASH" character, 0x2013. I wonder if you accidentally copy-and-pasted it from a web page. Oct 17, 2011 at 18:58
  • 7
    did rm -i * not work? Seems like it would do the same thing as the perl script.
    – user606723
    Oct 17, 2011 at 19:18
  • 2
    I'm guessing it originated from the web page at which I pointed the wget. In any case, thanks again for the thorough solution! take care.
    – jgrundstad
    Oct 17, 2011 at 19:35
  • 5
    perl -e 'unlink grep { print "remove $_? "; <STDIN> =~ /y/i } glob "*"' Oct 17, 2011 at 23:05
  • 6
    @RandalSchwartz: Impressively terse (and makes my brain hurt a bit) -- but I'd want /^y/i rather than /y/i. After all, a Russian user might type "Nyet". Oct 17, 2011 at 23:26
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 {} \;
3
  • 2
    +1 as this is a great general answer for these problems. By the way theres no need to used -exec rm in recent find's, just use -delete
    – Sirex
    Oct 17, 2011 at 21:22
  • 2
    @Sirex - I think the point of -exec rm -i {} is the -i to prompt for removal. I'm looking at man find and don't see any way to do that.
    – Stephen P
    Oct 18, 2011 at 0:41
  • oh yes, in this case. was more of a tip.
    – Sirex
    Oct 18, 2011 at 21:02
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 ./-.

2
  • 8
    Rather than typing 30 characters, perhaps it would have been more useful to explain why the / helps parse correctly
    – Ivo Flipse
    Oct 17, 2011 at 20:42
  • @gcb Thanks for the proposed edit. I added code markup to that, so it would be easier to read.
    – slhck
    Oct 18, 2011 at 9:33
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.

1
  • +1 for cleverly side-stepping the issue - and that without even resorting to a GUI program.
    – sleske
    Jan 4, 2012 at 11:14
7

Try:

$ ls -b

to see if the filename has unprintable characters.

1
  • Why the downvote? Given the followup, this sounds like a very good suggestion. Oct 18, 2011 at 11:18
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: $!"'
1
  • This method has the advantage that there are no special characters to worry about (other than string quoting issues).
    – Kevin Reid
    Oct 17, 2011 at 18:33
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 $! } }' -- *
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
  • 1
    I'm guessing that there is no such file or directory, and perhaps the file name also contains some invisible character(s). (and you could get about the same error message in perl with 'unlink "-" or die "Err: $!"'). Try "ls -b" to see what the real filename is.
    – runrig
    Oct 17, 2011 at 20:27
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.

4
  • in Ubuntu: ~/jj$ rm -rf '-' ~/jj$ ls –
    – user999624
    Oct 17, 2011 at 17:13
  • rm - works for me too.
    – uzsolt
    Oct 17, 2011 at 17:50
  • 1
    Why -r ? Requesting a recursive deletion if you don't need it is always dangerous in case of mispelings. Oct 21, 2011 at 6:15
  • @hstoerr, good point. just habbit. hands type faster than brain. editing response now, thanks.
    – Lucas
    Oct 21, 2011 at 10:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .