DEV Community

morgana
morgana

Posted on • Originally published at morgandadams.com on

Deleting files that start with a hyphen in Bash

The Stage

I ran a script that takes a file path as an argument and it writes to that file. First, I ran it with the -h flag to see if I could get a help message. No error message printed to stdout. However, the script then did something unexpected…

After pressing enter, the script continued execution and prompted for additional input. I didn’t notice and hit “enter” a couple of times to get a clean prompt. This inadvertently allowed the script to finish. As a result, I ended up with a brand new file call “-h”. Oops.

Deleting a file is hard…

No big deal right?

$> ls
-h
Enter fullscreen mode Exit fullscreen mode

We can just delete that with a simple “rm” command

$> rm -h
rm: invalid option -- 'h'
Try 'rm ./-h' to remove the file '-h'.
Try 'rm --help' for more information.
Enter fullscreen mode Exit fullscreen mode

What…?

$> rm \-h
rm: invalid option -- 'h'
Try 'rm ./-h' to remove the file '-h'.
Try 'rm --help' for more information.
$>
$> rm "-h"
rm: invalid option -- 'h'
Try 'rm ./-h' to remove the file '-h'.
Try 'rm --help' for more information.
$>
$> rm '-h'
rm: invalid option -- 'h'
Try 'rm ./-h' to remove the file '-h'.
Try 'rm --help' for more information.
$>
$> rm '\-h'
rm: cannot remove '\-h': No such file or directory
Enter fullscreen mode Exit fullscreen mode

At this point, I scratched my head in confusion. However, after some Googling I found a couple of simple solutions

$>rm ./-h
# or
$>rm -- -h
Enter fullscreen mode Exit fullscreen mode

Either of these solutions works. The first works because we’re using the current directory as part of the path. This tells bash not to process the hyphen as an option.

Finally, the second option works because the double hyphen is a bash built-in. It tells the command that there are no more options to process and that anything else is a positional argument.

Wrap-up

In conclusion, I have a few lessons learned:

  1. Actually look at your prompt before pressing enter
  2. Shells have a lot of nuances. It’s worth taking the time to learn about them when you encounter them because you’ll likely run into them again.
  3. Use “set -e” in your scripts. If there is an error, the script will exit rather than continue execution.

Top comments (8)

Collapse
 
vezyank profile image
Slava

rm \\-h is closer to what you may consider standard.

Collapse
 
_morgan_adams_ profile image
morgana

You would think, but that's not the case. At least not in bash. I haven't tried in other shells.

morgana@DESKTOP-23M0CRD:~/testrm$ ll
total 0
-rw-rw-rw- 1 morgana morgana 0 Jan 31 17:13 -h
morgana@DESKTOP-23M0CRD:~/testrm$ rm \\-h
rm: cannot remove '\-h': No such file or directory
morgana@DESKTOP-23M0CRD:~/testrm$ rm \-h
rm: invalid option -- 'h'
Try 'rm ./-h' to remove the file '-h'.
Try 'rm --help' for more information.
morgana@DESKTOP-23M0CRD:~/testrm$
Collapse
 
vezyank profile image
Slava

Whack. Works on my machine.

Thread Thread
 
_morgan_adams_ profile image
morgana

Which shell are you running? Version? I would like to try it out.

Thread Thread
 
vezyank profile image
Slava

Ah that might be it. I’m on zsh. I never really encountered actual shell differences before.

Collapse
 
makhauser profile image
mkh

Just in case you can always find the file by its inode and remove it. But these variants are faster of course.

Just in case:

$ ls -i
$ find . -inum $INODE -exec rm -i {} \;

Collapse
 
_morgan_adams_ profile image
morgana

Nice one!

I'm going to work that into my post and credit you with that one if that's okay.

I knew you could use ls to see inode info, but I didn't know you could use inode info with find.

Collapse
 
makhauser profile image
mkh

Sure you can, but that is an old instruction, don't even remember where I have found it. Most likely on the Cybercity. What is good in this trick - you can delete the file with any naming issues either it has slashes, dashes or whatever.