Como faço para remover um arquivo no Linux cujo nome parece ser apenas um hífen, como em "-"

33

eu tentei

rm -- -
rm "-"
rm "\-"
rm \-

Deu uma chance a Perl

~$ perl -e '$junk = glob("-"); chomp $junk; print "$junk\n"; `rm $junk`;'
-
rm: cannot remove `-': No such file or directory

...e...

~$ perl -e '$junk = glob("-"); chomp $junk; print "$junk\n"; `mv $junk newfile.garbage`;'
-
mv: cannot stat `-': No such file or directory

Qualquer ajuda seria muito apreciada, pessoas sábias.

jgrundstad
fonte
Por curiosidade, como chegou lá?
Petey B
2
Foi o resultado de um wget mal construído: "wget ​​-q -O - someserver.org/s/ip "
53
Lembra-me da época em que um colega criou um arquivo chamado *. Esta história não terminou bem.
David Heffernan
Qual rmversão você está usando ( rm --version)? rm -funciona bem com o GNU coreutils 8.5.
Lekensteyn
2
Outra variante:rm ./-
um CVn

Respostas:

60

Isso costumava ser publicado nas perguntas frequentes da Usenet para Unix - vejo que está nas perguntas frequentes do GNU Core Utility . Havia pelo menos cinco métodos diferentes, mas isso funciona bem:

$ rm ./-

Se um nome de arquivo contiver caracteres não tipáveis, use:

$ rm -i *

A -ibandeira pede confirmação para cada arquivo se ele deve ser removido ou não.

Wallyk
fonte
1
Ou rm -i - ' - ' se você estiver procurando por arquivos contendo um hífen e talvez alguns espaços ou o que for.
Hans-Peter Störr 21/10
1
rm -i * também funcionou para mim. Obrigado wallyk!
jgrundstad
39

A remoção de um arquivo cujos nomes começam -é uma FAQ, mas parece que você tem um problema diferente.

Das soluções que você mencionou na pergunta:

rm -- -

Isso deve funcionar.

rm "-"

Isso não é diferente de rm -. As aspas são removidas pelo shell, e o rmcomando apenas vê o hífen único como argumento. As aspas são úteis para escapar dos metacaracteres do shell; o hífen é especial para rm, não para o shell.

rm "\-"

As aspas escapam da barra invertida; portanto, isso tenta remover um arquivo cujo nome consiste em dois caracteres, uma barra invertida e um hífen.

rm \-

Isto é como rm "-", equivalente a rm -.

Por acaso, pelo menos com a versão GNU coreutils rm, rm -na verdade remove (ou tenta remover) um arquivo cujo nome consiste apenas em um hífen. Se seu arquivo tivesse esse nome, ele já estaria esgotado. Concluo que seu arquivo tem um nome que se parece apenas com um hífen.

ls | cat -A

deve dar uma idéia do que realmente é chamado.

Aqui está um script Perl que acabei de juntar que solicitará cada arquivo no diretório atual e perguntará se deseja removê-lo. Oferecido sem garantia, mas eu o testei brevemente.

#!/usr/bin/perl

use strict;
use warnings;

$| = 1;

opendir my $DIR, '.' or die ".: $!\n";
my @files = sort grep { -f $_ } readdir $DIR;
closedir $DIR;

foreach my $file (@files) {
    print "Remove $file? ";
    my $answer = scalar <>;
    if ($answer =~ /^[Yy]/) {
        unlink $file or warn "$file: $!\n";
    }
    elsif ($answer =~ /^[Qq]/) {
        exit 0;
    }
}

EDIT : Uma solução menos elaborada: se o nome do arquivo for apenas um caractere, rm ?remova-o (junto com outros arquivos).

Keith Thompson
fonte
13
M-bM-^@M-^Sé uma representação da representação UTF-8 de 3 bytes do caractere Unicode "EN DASH", 0x2013. Gostaria de saber se você acidentalmente copiou e colou de uma página da web.
21711 Keith Thompson
7
se rm -i *não funcionar? Parece que faria a mesma coisa que o script perl.
user606723
2
Acho que ele se originou da página da web em que apontei o wget. De qualquer forma, obrigado novamente pela solução completa! cuidar.
jgrundstad
5
perl -e 'desvincule grep {print "remove $ _?"; <STDIN> = ~ / y / i} glob "*" '
Randal Schwartz
6
@RandalSchwartz: Impressionantemente conciso (e faz meu cérebro doer um pouco) - mas eu /^y/ipreferiria /y/i. Afinal, um usuário russo pode digitar "Nyet".
Keith Thompson
19

Se você quer algo mais seguro ...

Tente usar uma combinação de ls e find (isso funciona para qualquer arquivo que você tenha permissão para remover)

O parâmetro '-i' fornecerá o número do inode para cada entrada de diretório ls -li

27 ----------  1 owner  group       3981 Oct 11 04:42 ?????

Depois de ter o número do inode ...

find . -inum **27** -exec rm -i {} \;
Sam
fonte
2
+1, pois essa é uma ótima resposta geral para esses problemas. A propósito não há necessidade de rm -exec usado na recente descoberta de, basta usar -delete
Sirex
2
@ Sirex - Eu acho que o objetivo -exec rm -i {}é -isolicitar a remoção. Estou olhando man finde não vejo nenhuma maneira de fazer isso.
Stephen P
ah sim, neste caso. foi mais uma dica.
Sirex
13

rm ./-uma chance.

O -sinalizador é para iniciar um argumento de sinalizador. Se você iniciar o argumento com qualquer coisa, exceto a -, nesse caso /, ele assumirá que é o nome do arquivo. Qual é o que você deseja.

E já que filee ./filesão o mesmo arquivo, ele terá como alvo o arquivo nomeado -via ./-.

Petey B
fonte
8
Ao invés de digitar 30 caracteres, talvez teria sido mais útil para explicar por que o / ajuda analisar corretamente
Ivo Flipse
@gcb Obrigado pela edição proposta. Eu adicionei a marcação de código a isso, para que fosse mais fácil ler.
slhck
7

Não é tão nerd quanto a maioria das outras respostas, mas eu acionava uma instância de mccomandante da meia-noite e apenas selecionava e excluía o arquivo.

johanvdw
fonte
+1 por contornar a questão de maneira inteligente - e isso sem sequer recorrer a um programa de GUI.
sleske
7

Experimentar:

$ ls -b

para ver se o nome do arquivo possui caracteres não imprimíveis.

Noel Yap
fonte
Por que o voto negativo? Dado o acompanhamento , isso soa como uma sugestão muito boa.
Ilmari Karonen
6

Não que seja necessário usar o perl aqui, mas isso deve funcionar:

perl -e 'unlink "-"'

ou para ver qual pode ser o erro acima:

perl -e 'unlink "-" or die "Err: $!"'
runrig
fonte
Este método tem a vantagem de não haver caracteres especiais com os quais se preocupar (além dos problemas de citação de string).
Kevin Reid
3

Eu tive sorte usando o Nautilus do GNOME para remover arquivos mal nomeados. Você está executando um servidor X? Tenho certeza de que outros navegadores de arquivos também funcionarão.

Joel Berger
fonte
3

E se

rm -- -

não funcionou, o nome do arquivo não é "apenas um hífen". Se nenhum outro arquivo tiver um hífen, tente tentar

perl -E'for (@_) { if (/-/) { unlink($_) or die $! } }' -- *
ikegami
fonte
1

Até agora, recebo um "Nenhum arquivo ou diretório" para todos os métodos publicados até agora:

rm ./-
rm -- -
mv "-" test.txt
rm -rf '-' <-- this gives no error, but doesn't work
perl -e 'unlink "-";'  <--also no error, doesn't work.

Parece que eu tenho a versão 7.4 do rm. Vou tentar atualizar e tentar novamente essas sugestões. Obrigado a todos por ajudar.

jgrundstad
fonte
1
Estou supondo que não exista esse arquivo ou diretório, e talvez o nome do arquivo também contenha alguns caracteres invisíveis. (e você pode receber a mesma mensagem de erro em perl com 'unlink "-" ou morre "Err: $!"'). Tente "ls -b" para ver qual é o nome do arquivo real.
Runrig
1

Eu gosto muito de usar o diredmodo no emacs para esse tipo de coisa - basta "abrir" o diretório no emacs. Você pode facilmente selecionar arquivos e marcá-los para exclusão.

Outro pôster sugeriu o uso do comandante da meia-noite; essa é praticamente a mesma idéia, mas se você já é usuário do emacs, talvez seja mais conveniente.

Ernest Friedman-Hill
fonte
0

Deve ser capaz de rm -f '-'trabalhar para mim no cygwin

Por falar nisso, rm -também parece funcionar no red hat.

Lucas
fonte
No Ubuntu: ~ / jj $ rm -rf '-' ~ / jj $ ls -
rm -funciona para mim também.
Uzsolt 17/10/11
1
Por que -r? Solicitar uma exclusão recursiva, se você não precisar, é sempre perigoso em caso de erros de digitação.
Hans-Peter Störr 21/10
@hstoerr, bom ponto. apenas habbit. mãos digitam mais rápido que o cérebro. resposta de edição agora, obrigado.
21411 Lucas