«Нет такого файла или каталога» при попытке удалить файл, но файл существует?

21

Я пытаюсь удалить изображение PNG, которое было загружено на мой сервер с помощью сценария PHP. Всякий раз, когда я пытаюсь удалить его как через FTP и терминал, я получаю сообщение об ошибке

No such file or directory

Однако, когда я lsв директории, файл указан в списке, и он также указан в моем FTP-клиенте. Я попытался создать файл с тем же именем, и я получаю два файла с одинаковым именем.

Я могу открыть файл, который предположительно не существует, но я все еще не могу удалить его. Я также попытался перезагрузить свой сервер. Есть идеи, в чем может быть проблема? Я использую 64-битную версию Ubuntu, но не думаю, что это 32/64-битная проблема. Я должен также отметить, что я удалил много других файлов png, загруженных тем же PHP-скриптом.

Выход для 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

Вывод при попытке rm

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

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

DevinFrench
источник
Скопируйте и вставьте выходные данные ls -lиз каталога, а также полную rmкоманду и ее выходные данные.
heemayl
@heemayl всего 224 -rw-r - r-- 1 www-data www-data 222838 13 мая 04:14 qyxdshyikfr_fishing_timeout.png -rw-r - r-- 1 корневой корень 272 14 мая 06:54 upload.php rm: невозможно удалить 'qyxdshyikfr_fishing_timeout.png': нет такого файла или каталога
DevinFrench
1
@DevinFrench Пожалуйста, отредактируйте свой вопрос, чтобы добавить информацию.
Муру
Из какого каталога вы запускаете rmкоманду?
Heemayl
1
@ Самуэль Почему это может указывать на проблему с файловой системой? unlinkВызов всегда будет не в состоянии найти файл , который не существует. Когда я запускаю эту straceкоманду в моей системе, где я знаю, что у меня нет такого файла, она выдает похожий вывод; Я не думаю , что указывает на то у меня есть проблема файловой системы! Кажется гораздо более вероятным, что имя файла немного отличается от qyxdshyikfr_fishing_timeout.pngпростого и выглядит одинаково из-за ограничений способа lsотображения имен файлов, как это предлагается в других ответах.
Элия ​​Каган

Ответы:

21

Я попытался создать файл с тем же именем, и я получаю два файла с одинаковым именем.

Это означает, что при отсутствии повреждения файловой системы у вас есть два файла с двумя разными именами, которые выглядят одинаково из-за непечатаемых символов или символов, которые выглядят одинаково в вашем наборе символов / шрифте. --escapeВариантом lsявляется вашим другом в таких случаях, как и инструменты , такие как cat -v.

Так тоже есть rm -i -- *

дальнейшее чтение

JdeBP
источник
Я был создателем файла и имени файла, который был загружен. Никто не пытался саботировать мой сервер, так как я единственный человек, который знает полный путь к upload.php. Однако добился цели rm -i -- *.
DevinFrench
3
@DevinFrench Если этот ответ решил вашу проблему, пометьте его как принятый, щелкнув отметку под счетчиком голосов, чтобы будущие пользователи могли знать о том, что это решение сработало для вас.
Кос
1
Может кто-нибудь объяснить rm -i -- *команду?
user3731622
Из того, что я понимаю: Passing -i подскажет вам перед удалением каждого файла. --before *выбирает все файлы независимо от того, содержат ли их имена специальные символы. Ссылка: https://explainshell.com/explain?cmd=rm+-i+--+*
MoltenMuffins
16

TL; DR: Запустить ls -1b, найти имя файла, скопировать строку, в которой оно появляется, и передать его rm.

Как и предполагали другие, скорее всего, это связано с ограничениями в способе ls- и некоторые другие программы, включая клиентское и серверное программное обеспечение - обрабатывают странные имена файлов, например, содержащие управляющие символы, по умолчанию. Ваш успех с ответом JdeBP убедительно свидетельствует о том, что так оно и было, хотя и до этого было бы неплохо.

  • Поскольку ls, когда стандартный вывод является терминалом, ?символы печатаются на своем месте. Поэтому, если вы не передаете lsвыходные данные какой-либо другой команде (или перенаправляете ее в журнал для просмотра), возможно, ваше имя файла не содержит управляющих символов. Но есть и другие проблемные символы - например, имя файла содержит конечные пробелы.

    Такое поведение lsможет сбивать с толку, но не является ошибкой, может быть явно изменено пользователем (см. Ниже).

  • При попытке получить доступ к файлу или удалить его удаленно, ошибки в клиентском или серверном программном обеспечении могут привести к таким проблемам.

    Я сталкивался с подобными вещами через ftpсебя несколько раз , в том числе для файлов, имена которых содержат завершающие пробелы. (То, что это не сработало, было связано с ошибкой в ​​моем ftp-клиенте.) Даже когда вы вручную создаете файл, в зависимости от того, как вы его создаете, иногда довольно легко случайно вставить конечный пробел или другой пробел, который может выглядеть как пространство, хотя это не так.

Это ситуация, когда ls -1b(или dir -1) пригодится:

  • -1говорит lsпоказывать одну запись в строке. Таким образом, не возникает путаницы в том, где заканчивается одно имя файла и начинается другое. Это удобно для файлов со странными именами.
  • -bговорит lsпечатать escape-последовательности для любых специальных символов. Вывод команды ls -bможно скопировать и вставить буквально в команду без добавления кавычек : все проблемные символы уже заключены в кавычки таким образом, что оболочка распознает их такими, какие они есть.

Предостережение только одно: если последний символ в строке выглядит так \, скопируйте один символ после него, поскольку это означает \пробел в кавычках.

Вы можете ls -1bпросто запустить его или передать ему шаблон оболочки (например, ls -1b qyx*). Globbing может или не может найти файл, в зависимости от того, присутствуют или нет управляющие символы (или другие странные символы) в той части имени, которая появляется в шаблоне glob.

Скопировав \версию, указанную вами в кавычках ls, вы можете вставить ее в команду. Вам не нужно изменять его вручную каким-либо образом. В вашем случае, если вы хотите удалить файл, введите rm, введите пробел, вставьте строку и нажмите Enter.

Дальнейшее чтение:

Элия ​​Каган
источник
1
Очень крутые -bспасибо =) и +1
AB
Что-то, что я исключил из OP, было, когда я создавал файл с тем же именем, в моем FTP-клиенте, когда я пытался удалить первый файл, с которым у меня были проблемы, он вместо этого удалял новый файл, который я создал. Вот почему я не думал, что были задействованы какие-либо специальные символы, и я до сих пор не знаю, что это был за особый персонаж с тех пор, как использовал rm -i -- *.
DevinFrench
@DevinFrench Дополнительный символ - это пробел в конце имени файла. Он все еще находится в lsвыводе вопроса, но его можно увидеть только в текстовом режиме, когда вы нажмете «изменить».
Изката
@Izkata Хороший звонок! Я должен был подумать, чтобы проверить это. Он также появляется, когда я раскрываю редакцию 3 в истории редактирования (полное имя файла, включая завершающий пробел, выделяется зеленым цветом и, таким образом, различимо). То, что вы сказали, является наиболее точным и конкретно правильным объяснением на данный момент - если вы опубликовали ответ, объясняющий, что он из конечного пробела, и откуда вы знаете, и какая команда удалит файл (если у ОП все еще был) Я знаю, я бы проголосовал за это.
Элия ​​Каган
@EliahKagan Готово, с картинками
Изката
3
  1. Используйте findи проверьте вывод:

    Если файл не найден, следует *qyxdshyikfr*немного сократить поисковый запрос, например: *qyxds*или *fishing*.

    sudo find . -maxdepth 1 -type f -name "*qyxdshyikfr*"
    
  2. Если все в порядке, используйте findтермин поиска на шаге 1 иrm

    find . -maxdepth 1 -type f -name "*qyxdshyikfr*" -print0 | xargs -0  rm
    
AB
источник
1
Вместо того , чтобы вызывать rmпо имени по трубе от findдо xargs, я рекомендую просто использовать find«s -deleteдействия. Также sudoне нужно. Менее существенно, я предлагаю опустить, -type fкроме случаев, когда это явно полезно. Предположительно, если запись, которую ОП хочет удалить, оказалась символической ссылкой, например, они все равно захотят ее найти и все равно захотят ее удалить. -deleteДействие не будет рекурсивно затирать каталог; и не будет вашей rmкоманды, так как у вас нет -r. Таким образом, вы не собираетесь случайно ударить целую (непустую) папку здесь, не используя -type.
Элия ​​Каган
Хорошо, дай мне секунду.
AB
В моем случае, даже find ... -deleteговорит: «не могу удалить ... Нет такого файла или каталога»
Stop Harming Monica
1

Перепечатка подробно, дополнена моим комментарием к ответу Елии

Проблема невидима, но ее можно увидеть, если вы знаете, что искать: имя файла содержит пробел в конце. Поскольку вы копируете / вставляете весь lsвывод, это можно увидеть в вопросе, выделите ли вы вывод или отредактируете сообщение и переместите курсор в конец, или (как указал Элия) посмотрите на разницу в истории редактирования. Я выделил lsвывод в посте на этом скриншоте:

Дополнительное пространство

Небольшая сессия терминала для дублирования проблемы с комментариями:

$ 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

Использование завершения табуляции также полностью обошло бы проблему, так как bash достаточно умен, чтобы правильно выходить из пробелов (в общем, это также хорошая привычка, так сильно ускоряет ввод путей) .

Например, если бы я набрал текст rm f<tab>, он автоматически завершился бы rm foo\<space><space>, как в последнем примере в блоке кода выше.

Izkata
источник
Я особо отмечаю копирование / вставку lsвывода, потому что нечто подобное произошло в StackOverflow один раз (и это единственная причина, по которой я подумал об этом): кто-то получил непечатный символ в своем коде, и единственная причина, по которой кто-то понял это. потому что этот пользователь также копирует / вставляет вместо повторного ввода своего кода при публикации вопроса
Изката
0

однажды я создал файл, чтобы открыть Nautilus от имени пользователя root, но имя файла при просмотре из nautilus было «Обозреватель файлов (root)», а затем при попытке удалить как

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

я получил только один ответ: «rm: невозможно удалить« File Browser (Root) .desktop »: такого файла или каталога нет»)

потом, когда я бегу:

$ ls -l

я видел / помнил, что имя файла, на самом деле, было "Nautilus-root.desktop"

так что я бегу:

$ sudo rm "Nautilus-root.desktop"

работал для меня, надеюсь, это помогает!

Вагнер Аркьери
источник
0

Так что у меня была эта проблема, и ничего из этого не помогло мне. Работало создание файла с точно таким же именем. Это была папка с именем Example.1.2.3, поэтому я создал новую папку и назвал ее точно такой же, как та, которая не будет удалена. Старая папка исчезла, а я удалил новую.

Джемисон лифси
источник
0

У меня была похожая ситуация, после того как я сделал rsyncрезервную копию моего каталога Pictures на Mac и прочитал его в Ubuntu. Было два файла (фактически каталоги) с разными именами, но с одинаковым содержимым. Я удалил одну в корзину (используя Nautilus), но не смог удалить другую, даже из командной строки. Было бы сказать:

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

После проверки номеров инодов с помощью ls -i -l оказалось, что оба каталога имеют одинаковый номер инода. Похоже на жесткую ссылку ...

Решение было удивительно простым - очистите корзину, щелкнув правой кнопкой мыши по значку. После этого оба каталога исчезли.

elomage
источник