“Não existe esse arquivo ou diretório” ao tentar remover um arquivo, mas o arquivo existe?

21

Estou tentando remover uma imagem png que foi carregada no meu servidor por meio de um script PHP. Sempre que tento excluí-lo através do ftp e do terminal, recebo o erro

No such file or directory

No entanto, quando estou lsno diretório, o arquivo é listado e também é listado no meu cliente ftp. Eu tentei criar um arquivo com o mesmo nome e acabei recebendo dois arquivos com o mesmo nome.

Posso abrir o arquivo que supostamente não existe, mas ainda não consigo removê-lo. Eu também tentei reiniciar meu servidor. Alguma idéia de qual pode ser o problema? Estou executando uma versão de 64 bits do Ubuntu, mas não acho que seja um problema de 32/64 bits. Devo também observar que removi muitos outros arquivos png carregados pelo mesmo script PHP.

Saída para 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

Saída ao tentar rm

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

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

DevinFrench
fonte
Copie e cole a saída ls -ldo diretório, também o pleno rmcomando e sua saída ..
heemayl
@heemayl total 224 -rw-r - r-- 1 www-data www-data 222838 13 de maio 04:14 qyxdshyikfr_fishing_timeout.png -rw-r - r-- 1 raiz raiz 272 maio 14 06:54 upload.php rm: não é possível remover 'qyxdshyikfr_fishing_timeout.png': Nenhum tal lima ou diretório
DevinFrench
1
@DevinFrench, edite sua pergunta para adicionar informações.
muru 14/05
De qual diretório você está executando o rmcomando?
heemayl 14/05
1
@ Samuel Por que isso sugere um problema no sistema de arquivos? A unlinkchamada sempre falha ao encontrar um arquivo que não existe. Quando executo esse stracecomando no meu sistema, onde sei que não tenho esse arquivo, ele produz uma saída semelhante; Eu não acho que isso indica que eu tenho um problema no sistema de arquivos! Parece muito mais provável que o nome do arquivo seja ligeiramente diferente qyxdshyikfr_fishing_timeout.pnge apenas apareça o mesmo devido às limitações na maneira lscomo os nomes dos arquivos são exibidos, conforme sugerido em outras respostas.
Eliah Kagan

Respostas:

21

Eu tentei criar um arquivo com o mesmo nome e acabei recebendo dois arquivos com o mesmo nome.

Isso significa que, na ausência de corrupção no sistema de arquivos, você tem dois arquivos com dois nomes diferentes que parecem iguais devido a caracteres não imprimíveis ou caracteres com a mesma aparência no seu conjunto de caracteres / fonte. A --escapeopção para lsé seu amigo nesses casos, assim como ferramentas como cat -v.

Então também é rm -i -- *

Leitura adicional

JdeBP
fonte
Eu fui o criador do arquivo e o nome do arquivo que foi carregado. Ninguém estava tentando sabotar meu servidor, pois sou a única pessoa que conhece o caminho completo para o upload.php No entanto, ele rm -i -- *fez o truque.
DevinFrench
3
@DevinFrench Se esta resposta resolveu seu problema, marque-a como resposta aceita clicando na marca abaixo da contagem de votos, para que futuros usuários possam estar cientes do fato de que essa solução funcionou para você.
kos
1
Alguém pode explicar o rm -i -- *comando?
user3731622 11/10
Pelo que entendi: A passagem -i solicitará a você antes da remoção de cada arquivo. --antes *seleciona todos os arquivos, independentemente de seus nomes incluírem caracteres especiais. Referência: https://explainshell.com/explain?cmd=rm+-i+--+*
MoltenMuffins
16

TL; DR: Execute ls -1b, encontre o nome do arquivo, copie a linha na qual ele aparece e forneça-o rm.

Como outros sugeriram, provavelmente isso se deve a limitações no caminho - lse alguns outros programas, incluindo software cliente e servidor - lidam com nomes de arquivos estranhos, como os que contêm caracteres de controle, por padrão. Seu sucesso com a resposta do JdeBP sugere fortemente que esse foi o caso, embora já tivesse sido uma boa aposta antes disso.

  • Pois ls, quando a saída padrão é um terminal, os ?caracteres são impressos em seu lugar. Portanto, se você não estiver lsdirecionando a saída para outro comando (ou redirecionando-a para um log para visualização), provavelmente seu nome de arquivo não contém caracteres de controle. Mas existem outros caracteres problemáticos - talvez o nome do arquivo contenha espaços em branco à direita, por exemplo.

    Esse comportamento de lspode ser confuso, mas não é um bug, pode ser substituído explicitamente pelo usuário (veja abaixo).

  • Ao tentar acessar ou remover um arquivo remotamente, os erros no software cliente ou servidor podem produzir esses problemas.

    Já experimentei esse tipo de coisa ftpvárias vezes , inclusive para arquivos cujos nomes contêm espaços à direita. (O fato de não ter funcionado ocorreu devido a um erro no meu cliente ftp.) Mesmo quando você mesmo cria um arquivo manualmente, dependendo de como o cria, às vezes é muito fácil inserir inadvertidamente um espaço à direita ou outro espaço em branco que pode parecer espaços, mesmo que não seja.

Essa é uma situação em que ls -1b(ou dir -1) é útil:

  • -1diz lspara mostrar uma entrada por linha. Dessa forma, não há confusão sobre onde um nome de arquivo termina e outro começa. Isso é útil para arquivos com nomes estranhos.
  • -bdiz lspara imprimir seqüências de escape para caracteres especiais. A saída de ls -bpode ser copiada e colada literalmente em um comando, sem nenhuma citação adicional : todos os caracteres problemáticos já são citados de uma maneira que faz com que o shell os reconheça como são.

Há apenas uma ressalva: se o último caractere de uma linha parece ser \, copie um caractere depois disso, pois isso significa \citar um espaço.

Você pode executar ls -1bassim, ou pode passar um padrão shell glob para ele (por exemplo, ls -1b qyx*). O globbing pode ou não encontrar o arquivo, dependendo se os caracteres de controle (ou outros caracteres estranhos) estão presentes na parte do nome que aparece no padrão glob.

Após copiar a \versão -quoted do nome de arquivo fornecido ls, você pode colá-lo em um comando. Você não precisa modificá-lo manualmente de forma alguma. No seu caso, como você deseja excluir o arquivo, digite rm, digite um espaço, cole a linha e pressione Enter.

Leitura adicional:

Eliah Kagan
fonte
1
Muito legal -bthx =) e +1
AB
Algo que deixei de fora do OP foi quando criei um arquivo com o mesmo nome, no meu cliente ftp, quando tentei excluir o primeiro arquivo com problemas, ele excluiria o novo arquivo que criei. Por isso, não achei que nenhum personagem especial estivesse envolvido e ainda não sei qual era o personagem especial desde que o usei rm -i -- *.
DevinFrench
@DevinFrench O caractere extra é um espaço no final do nome do arquivo. Ainda está na lssaída da pergunta, mas só pode ser visto no modo de texto quando você clica em "editar".
Izkata 14/05
@Izkata Good call! Eu deveria ter pensado em verificar isso. Também aparece quando eu expiro a revisão 3 no histórico de edições (o nome completo do arquivo, incluindo o espaço à direita, é destacado em verde e, portanto, discernível). O que você disse é a explicação mais definitiva e especificamente correta até agora - se você postou uma resposta explicando que é de um espaço à direita, e como você sabe, e que comando removeria o arquivo (se o OP ainda o tivesse) , Eu sei que eu iria votar.
Eliah Kagan
@EliahKagan Feito, com fotos
Izkata 15/15/15
3
  1. Use finde verifique a saída:

    Se o arquivo não for encontrado, reduza *qyxdshyikfr*ligeiramente o termo de pesquisa , por exemplo: *qyxds*ou *fishing*.

    sudo find . -maxdepth 1 -type f -name "*qyxdshyikfr*"
    
  2. Se estiver bem, use findo termo de pesquisa na etapa 1 erm

    find . -maxdepth 1 -type f -name "*qyxdshyikfr*" -print0 | xargs -0  rm
    
AB
fonte
1
Em vez de chamar rmpelo nome através de um canal de findpara xargs, eu recomendo simplesmente usar finda -deleteação de. Também sudonão é necessário. Menos significativamente, sugiro omitir, -type fexceto quando for claramente útil. Presumivelmente, se a entrada que o OP deseja excluir acabou por ser um link simbólico, por exemplo, eles ainda desejam encontrá-lo e ainda desejam excluí-lo. A -deleteação não recursivamente derruba um diretório; nem o seu rmcomando, uma vez que você não tem -r. Portanto, você não irá acidentalmente bater uma pasta inteira (não vazia) aqui por não usar -type.
Elias Kagan
OK, me dê um segundo.
AB
No meu caso, até find ... -deletediz "não é possível excluir ... Esse arquivo ou diretório"
Pare de prejudicar Monica
1

Repostando em detalhes, expandido do meu comentário sobre a resposta de Eliah

O problema é invisível, mas pode ser visto se você souber o que procurar: O nome do arquivo inclui um espaço no final. Como você copiou / colou toda a lssaída, isso pode ser visto na pergunta se você destacar a saída, ou editar a postagem e mover o cursor até o fim, ou (como Eliah apontou) examinar o diff no histórico de edições. Eu destaquei a lssaída no post nesta captura de tela:

Espaço extra

Uma pequena e rápida sessão de terminal para duplicar o problema, com comentários:

$ 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

Usar o preenchimento de guias também evitaria completamente o problema aqui, pois o bash é inteligente o suficiente para escapar dos espaços corretamente (também é um bom hábito, em geral, acelera muito os caminhos de digitação) .

Por exemplo, se eu tivesse digitado rm f<tab>, ele seria preenchido automaticamente rm foo\<space><space>, como no último exemplo no bloco de código acima.

Izkata
fonte
Faço menção especial de copiar / colar a lssaída porque algo semelhante aconteceu no StackOverflow uma vez (e é a razão pela qual pensei em procurar isso): alguém tem um caractere não imprimível em seu código e a única razão pela qual alguém descobriu isso é porque esse usuário também copiar / colar em vez de re-digitando seu código ao postar a pergunta
Izkata
0

uma vez, criei um arquivo para abrir o Nautilus como root, mas o nome do arquivo ao ver no nautilus era "File Browser (root)" e, em seguida, quando tentei remover como

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

a única resposta que recebi foi: "rm: não é possível remover 'File Browser (Root) .desktop': esse arquivo ou diretório não existe"

então quando eu corro:

$ ls -l

vi / lembrei que o nome do arquivo era "Nautilus-root.desktop"

então eu corro:

$ sudo rm "Nautilus-root.desktop"

trabalhou para mim, espero que ajude!

Wagner Arcieri
fonte
0

Então, eu tive esse problema e nenhuma dessas coisas funcionou para mim. O que funcionou foi a criação de um arquivo com o mesmo nome. Era uma pasta chamada Example.1.2.3, então criei uma nova pasta e a nomeei exatamente como a que não excluiria. A pasta antiga desapareceu e eu apaguei a nova.

Jamison Lifsey
fonte
0

Eu tive uma situação semelhante, depois de usar rsyncpara fazer backup do meu diretório Pictures em um Mac e lê-lo no Ubuntu. Havia dois arquivos (na verdade diretórios) com nomes diferentes, mas com o mesmo conteúdo. Excluí um no Lixo (usando o Nautilus), mas não consegui excluir o outro, mesmo na linha de comando. Diria:

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

Após verificar os números de inode com ls -i -l, verificou-se que os dois diretórios têm o mesmo número de inode. Parece um link rígido ...

A solução foi surpreendentemente simples - esvazie a lixeira clicando com o botão direito do mouse no ícone. Depois disso, os dois diretórios sumiram.

elomage
fonte