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.

up vote 5 down vote accepted

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'
  • 1
    Backslashes inside double-quotes only escape double-quotes, backslashes and backticks, so rm ".\*" would work too. (try echo " \" \* \' \\ ") Though single-quotes are clearer since at least the backslash is always a regular character there. – ilkkachu Aug 14 at 21:41
  • Good point, @ilkkachu. Then you get in to the third behavior of $'string', depending on the shell... Best not to rely on something "probably" working. :D – dannysauer Aug 14 at 21:51
  • @ilkkachu That's absolutely worth pointing out for someone learning the full set of shell escaping rules. That said, with someone doesn't know anything about shell escapes (as is the case with the person asking here) I always teach them single-quotes first, because I've seen far more non-obvious hard-to-debug problems from people aiming for literal strings and not remembering that some characters are special in double-quotes than than I've seen from people accidentally not getting the special interpretation they want from single-quotes. – mtraceur Aug 14 at 22:58

Since the filenames contain an escape character \, you need to escape that escape character.

rm .\\gitkeep .\\innerfile\\gitkeep
rmdir .\\innerfile 

will remove your files

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.