46

I am trying to remove a png image that was uploaded to my server via a PHP script. Whenever I try to delete it both through ftp and terminal, I get the error

No such file or directory

However, when I ls in the dir, the file is listed and it is also listed in my ftp client. I have tried creating a file with the same name and I end up getting two files with the same name.

I can open the file that supposedly does not exist, but I still can't remove it. I have also tried rebooting my server. Any ideas what may be the issue? I am running a 64 bit version of Ubuntu, but I don't think its a 32/64 bit issue. I should also note I have removed many other png files uploaded by the same PHP script.

Output for ls -l

total 224 
-rw-r--r-- 1 www-data www-data 222838 May 13 04:14 qyxdshyikfr_fishing_timeout.png 
-rw-r--r-- 1 root root 272 May 14 06:54 upload.php

Output when trying to rm

rm: cannot remove ‘qyxdshyikfr_fishing_timeout.png’: No such file or directory

upload.php: http://pastebin.com/z87eypTY

12
  • Copy paste the output of ls -l from the directory, also the full rm command and its output..
    – heemayl
    May 14, 2015 at 11:19
  • @heemayl total 224 -rw-r--r-- 1 www-data www-data 222838 May 13 04:14 qyxdshyikfr_fishing_timeout.png -rw-r--r-- 1 root root 272 May 14 06:54 upload.php rm: cannot remove ‘qyxdshyikfr_fishing_timeout.png’: No such file or directory May 14, 2015 at 11:24
  • 1
    @DevinFrench please edit your question to add information.
    – muru
    May 14, 2015 at 11:25
  • From which directory you are running the rm command ?
    – heemayl
    May 14, 2015 at 11:36
  • 1
    @Samuel Why would this suggest a filesystem problem? The unlink call will always fail to find a file that doesn't exist. When I run that strace command on my system, where I know I have no such file, it produces similar output; I don't think that indicates I have a filesystem problem! It seems far more likely that the file's name is slightly different from qyxdshyikfr_fishing_timeout.png and merely appears the same due to limitations in the way ls displays filenames, as suggested in other answers. May 14, 2015 at 17:21

7 Answers 7

24

I have tried creating a file with the same name and I end up getting two files with the same name.

That says, absent filesystem corruption, that you have two files with two different names that appear the same because of non-printing characters or characters that look the same in your character set/font. The --escape option to ls is your friend in such instances, as are tools such as cat -v.

So, too, is rm -i -- *

Further reading

5
  • I was the creator of the file and the file name that was uploaded. No one was trying to sabotage my server as I am the only person that knows the complete path to upload.php However, rm -i -- * did the trick. May 14, 2015 at 11:58
  • 3
    @DevinFrench If this answer solved your problem, please mark it as the accepted answer by clicking the mark under the upvotes count, so that future users might be aware of the fact that this solution worked for you.
    – kos
    May 14, 2015 at 12:05
  • 1
    Can someone explain rm -i -- * command? Oct 11, 2019 at 2:53
  • From what I understand: Passing -i will prompt you before removal of each file. -- before * selects all files regardless of whether their names include special characters. Reference: https://explainshell.com/explain?cmd=rm+-i+--+* Nov 19, 2019 at 8:01
  • 6
    rm -i -- * was ineffective. Although I was asked to confirm deletion of each item. On affirmation, rm: cannot remove '_index.txt~': No such file or directory. Nevertheless, the file is catable. Oct 10, 2020 at 18:28
16

TL;DR: Run ls -1b, find the filename, copy the line on which it appears, and give that to rm.

As others have suggested, most likely this is due to limitations in the way ls--and some other programs, including client and server software--handle weird filenames, such as those containing control characters, by default. Your success with JdeBP's answer strongly suggests this was the case, though it would've been a good bet even before that.

  • For ls, when standard output is a terminal, ? characters are printed in their place. So if you're not piping ls's output to any other command (or redirecting it to a log for viewing), probably your filename doesn't contain control characters. But there are other problematic characters--perhaps the filename contains trailing whitespace, for example.

    This behavior of ls can be confusing but is not a bug, can can be overridden explicitly by the user (see below).

  • When attempting to access or remove a file remotely, bugs in client or server software can produce such problems.

    I've experienced this sort of thing via ftp myself several times, including for files whose names contain trailing spaces. (That it didn't work was due to a bug in my ftp client.) Even when you manually create a file yourself, depending on how you are creating it, it's sometimes quite easy to inadvertently insert a trailing space, or other whitespace that may look like spaces even though it isn't.

This is a situation where ls -1b (or dir -1) comes in handy:

  • -1 tells ls to show one entry per line. That way there is no confusion about where one filename ends and another begins. This is handy for weirdly named files.
  • -b tells ls to print escape sequences for any special characters. The output of ls -b can be copied and pasted literally into a command, with no added quoting: all problematic characters are already quoted in a way that causes the shell to recognize them as what they are.

There is only one caveat: if the last character on a line appears to be \, copy one character after that, since this means \ is quoting a space.

You can run ls -1b just like that, or you can pass a shell glob pattern to it (e.g., ls -1b qyx*). Globbing may or may not find the file, depending on whether or not the control characters (or other weird characters) are present in the portion of the name appearing in the glob pattern.

Having copied the \-quoted version of the filename given to you by ls, you can paste this into a command. You don't have to modify it manually in any way. In your case, as you wish to delete the file, type rm, type a space, paste the line, and press Enter.

Further reading:

6
  • 1
    Very cool -b thx =) and +1
    – A.B.
    May 14, 2015 at 18:02
  • Something I left out of OP was when I created a file with the same name, in my ftp client when I tried to delete the first file that I was having issues with, it would instead delete the new file that I made. That is why I didn't think any special characters were involved, and I still don't know what the special character was since I used rm -i -- *. May 14, 2015 at 21:06
  • @DevinFrench The extra character is a space at the end of the file name. It's still in the ls output in the question, but can only be seen in text mode when you click "edit".
    – Izkata
    May 14, 2015 at 21:41
  • @Izkata Good call! I should've thought to check that. It also appears when I expand revision 3 in the edit history (the full filename, including the trailing space, is highlighted in green and thus discernible). What you've said is the most definitive and specifically correct explanation so far--if you posted an answer explaining that it's from a trailing space, and how you know, and what command would remove the file (if the OP still had it), I know I'd upvote it. May 15, 2015 at 0:57
  • @EliahKagan Done, with pictures
    – Izkata
    May 15, 2015 at 3:10
5

So I had this problem and none of these things worked for me. What worked was creating a file with the exact same name. It was a folder named Example.1.2.3 so I created a new folder and named it the exact same as the one that wouldn't delete. The old folder disappeared and I deleted the new one.

3
  1. Use find and check the output:

    If the file is not found, then shortening the search term *qyxdshyikfr* slightly, eg: *qyxds* or *fishing*.

     sudo find . -maxdepth 1 -type f -name "*qyxdshyikfr*"
    
  2. If ok, than use find with the search term in step 1 and rm

     find . -maxdepth 1 -type f -name "*qyxdshyikfr*" -print0 | xargs -0  rm
    
3
  • 2
    Rather than calling rm by name via a pipe from find to xargs, I recommend simply using find's -delete action. Also sudo isn't needed. Less significantly, I suggest omitting -type f except where it's clearly helpful. Presumably if the entry the OP wants to delete turned out to be a symbolic link, for example, they'd still want to find it and still want to delete it. The -delete action won't recursively clobber a directory; neither will your rm command since you don't have -r. So you aren't going to accidentally whack a whole (non-empty) folder here by not using -type. May 15, 2015 at 1:05
  • OK, give me a second.
    – A.B.
    May 15, 2015 at 7:08
  • 2
    In my case, even find ... -delete says "cannot delete ... No such file or directory"
    – OrangeDog
    Dec 13, 2018 at 10:46
2

Reposting in detail, expanded from my comment on Eliah's answer

The problem is invisible, but can be seen if you know what to look for: The file name includes a space at the end. Because you copy/pasted the entire ls output, it can be seen in the question if you highlight the output, or edit the post and move the cursor to the end, or (as Eliah pointed out) look at the diff in the edit history. I highlighted the ls output in the post in this screenshot:

Extra space

A quick little terminal session to duplicate the problem, with comments:

$ touch 'foo '        # Create file with a space at the end
$ ls -l               # Space is not visible in ls output
total 0
-rw-rw-r-- 1 izkata izkata 0 May 14 21:59 foo 

$ rm foo              # Cannot remove it when not specifying the space
rm: cannot remove ‘foo’: No such file or directory

$ rm 'foo '           # Can remove it if we quote the file name and include the space
$ rm foo\             # Or can escape the space to tell bash to include it as part of the filename

Using tab completion would have also completely sidestepped the problem here, as bash is smart enough to escape spaces correctly (It's also a good habit in general, speeds up typing paths so much).

For example, had I typed rm f<tab>, it would have auto-completed to rm foo\<space><space>, as in the last example in the code block above.

1
  • I make special mention of copy/pasting the ls output because something similar happened on StackOverflow once (and is the whole reason I thought to look for this): someone got a non-printable character in their code, and the only reason anyone figured it out is because that user also copy/pasted instead of re-typing their code when posting the question
    – Izkata
    May 15, 2015 at 3:14
0

once, i've created a file to open Nautilus as root, but the file name when seeing from nautilus was "File Browser (root)", then when i tried to remove as

$ rm "File Browser (Root)"
$ sudo rm "File Browser (Root)"
$ sudo rm "File Browser (Root).desktop"

the only anwser i got was: "rm: cannot remove 'File Browser (Root).desktop': No such file or directory"

then when i run:

$ ls -l

i saw/remembered that the file name, in fact, was "Nautilus-root.desktop"

so i run:

$ sudo rm "Nautilus-root.desktop"

worked for me, hope it helps !

0

I had a similar situation, after using rsync to backup my Pictures directory on a Mac and reading it on Ubuntu. There were two files (actually directories) with different names, but having the same content. I deleted one to the Trash (using Nautilus), but could not delete the other, even from the command line. It would say:

$ rmdir Pictures
rmdir: failed to remove 'Pictures': No such file or directory
$ rm Pictures
rm: cannot remove 'Pictures': Is a directory

After checking the inode numbers with ls -i -l it turned out that both directories have the same inode number. Looks like a hard link...

The solution was surprisingly simple - empty the Trash by right clicking on the icon. After that both directories were gone.

You must log in to answer this question.

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