5

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.

0

3 Answers 3

5

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'
3
  • 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, 2018 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, 2018 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, 2018 at 22:58
2

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

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

will remove your files

2

If everything else failed, you can do the following to delete files and folders that have backslashes or weird characters in their names:

rm -iR *

The above command will start the process of deleting everything on the folder where you are. However, it will prompt you before deleting each file or folder:

rm: remove regular file `.\gitkeep? y
rm: remove regular file `.\innerfile\gitkeep'? y

You will need to type "y" and press [Enter] for each file or folder that you want to delete. If you come across a file or folder that you do NOT want to delete, type "n" and press [Enter].

If you are still being prompted for all your remaining files & folders but you have already deleted what you wanted to, just press the following key combination:

[Ctrl] + [c]
1
  • 1
    Amazing answer, thank you. This easily solved my problem.
    – mynyml
    Feb 28, 2022 at 21:27

You must log in to answer this question.

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