Shell – How to delete or access a file with a backslash \ in its name

command linefilenamesquotingshell

I have some files here that I copied over to this linux box using the python module pysftp:

[jm@spartan tf]$ ls -la
total 0
drwxrwxrwx. 3 jm jm  69 Aug 14 13:50 .
drwxrwxrwt. 9 root    root    238 Aug 14 13:49 ..
-rwxrwxrwx. 1 jm jm   0 Aug 14 13:49 .\gitkeep
drwxrwxrwx. 2 jm jm   6 Aug 14 13:50 .\innerfile
-rwxrwxrwx. 1 jm jm   0 Aug 14 13:50 .\innerfile\gitkeep
[jm@spartan tf]$ rm .\gitkeep
rm: cannot remove ‘.gitkeep’: No such file or directory

They're hidden, so I'm still trying to figure out how to copy then over so they aren't hidden, but in the mean time I want to delete them, but I'm unable to. What's going on here?

I'm on CentOS 7.

Best Answer

What you really need to do is to fix your script so it converts the windows paths to Unix paths. One relatively easy way to do that is to take path separators out of the equation: rather than providing full path names to copy, you recursively walk directories, creating target directories on the remote side and specifying only the filename rather than the full path. :)

But until you get to that point, you need to protect the backslashes from the shell. You can do that by quoting using single quotes (backslashes are interpreted for some characters inside double quotes). Note specifically that the wildcard is outside of the quotes so the shell treats it as a wildcard rather than a literal *: :)

rm -rv '.\'*

Or you can do that by escaping the backslash (which would also work in double quotes, but the double quotes aren't needed here):

rm -rv .\\*

I would suggest that, before you remove stuff using a wildcard, you always first run ls with the same arguments, then use the up arrow to recall the last command, where you can change the ls to an rm. That way you can see the list of files before it's removed, preventing a potentially big mistake. :) I'm also a big fan of using -v with rm in cases like this.

sauer@lightning:/tmp> ls -vr .\\*
.\innerfile\gitkeep  .\gitkeep

.\innerfile:
sauer@lightning:/tmp> rm -vr .\\*
removed '.\gitkeep'
removed directory '.\innerfile'
removed '.\innerfile\gitkeep'
Related Question