Como excluo um arquivo cujo nome começa com "-" (hífen, também conhecido como traço ou menos)?

349

Como você remove um arquivo cujo nome de arquivo começa com um hífen (hífen ou menos) -? Estou ssh'd em um servidor OSX remoto e tenho este arquivo no meu diretório:

tohru:~ $ ls -l
total 8
-rw-r--r--    1 me  staff  1352 Aug 18 14:33 --help
...

Como no mundo posso excluir --helpde uma CLI? Esse problema é algo que, de vez em quando, me deparei com diferentes formas; esses arquivos são fáceis de criar, mas difíceis de se livrar.

Eu tentei usar barra invertida

rm \-\-help

Eu tentei aspas

rm "--help"

Como evito que o caractere de menos (traço ou hífen) seja interpretado como uma opção?

Bryan Rehbein
fonte
1
Seria ótimo se essa pergunta fosse renomeada para "Como excluir um arquivo cujo nome começa com -".
Sandy
@Sandy concordou; Normalmente não gosto de mudar o significado de uma pergunta, mas, neste caso, a resposta aceita é específica para esse problema
Michael Mrozek
33
Acho um pouco irônico que rm --helprealmente explica como excluir nomes de arquivos começando com a -. boa pergunta, no entanto.
lesmana
1
@ jw013 Às vezes, a ajuda é fácil para usuários experientes entenderem, mas esmagadora e confusa para os novatos.
Iconoclasta
1
Eu me deparei com isso em um sistema usando rm do BusyBox. Tudo é mínimo, incluindo a ajuda, portanto, rm --help não forneceu pistas.
dslake

Respostas:

497

Use "-" para fazer com que o rm pare de analisar as opções da linha de comando, assim:

rm -- --help
Vegar Nilsen
fonte
1
Eu sabia que era algo muito simples assim ...
Bryan Rehbein
2
Todas as versões do rmcomando suportam o --argumento?
Keith Thompson
3
@KeithThompson - é uma característica da maioria das ferramentas GNU, por isso não irá funcionar na maioria não-GNU Unix'es (por exemplo, variantes BSD alguns sistemas embarcados ou) ( "non-Linux")
DTECH
1
OBRIGADO! Isso salvou o meu dia. E é claro que funciona em BSD (OSX) e com outros comandos!
raskhadafi
8
@dtech, getopt () e --anterior ao GNU (SysIII, 1980) e são padrão / POSIX. Utilitários padrão, exceto por algumas exceções (como echo), entendem --. YMMV para outros comandos se eles não usarem a API getopt () para analisar as opções.
Stéphane Chazelas
214

Ou você pode fazer

rm ./--help
edfuh
fonte
7
Não que isso importe, mas isso parece o mais "adequado".
James M.
2
Esse é o que eu lembro. Usar "rm - --help" é algo que sempre preciso procurar.
user603
25
Esse método sempre funciona mesmo para comandos que não tratam --especialmente.
jw013
E também funciona para evitar o tratamento especial por parte de alguns comandos para outros tipos (ao lado de opções) de argumentos especialmente nomeados como o -de utilitários de texto ou cd, o foo=barde awk...
Stéphane Chazelas
1
Isso funciona quando um arquivo começa com um único traço, onde rm -- <filename>não.
StockB
37

Use findpara fazer isso:

find . -name '--help' -delete

E este é um bom método, porque se você tiver mais do que alguns arquivos como esse, poderá excluir uma lista de visualização dos arquivos, simplesmente executando find sem a -deleteopção primeiro e, em seguida, se a lista de arquivos parecer boa, basta executar novamente com -delete.

De fato, você evitar a rmfavor de find(especialmente com a visualização prévia) é um bom hábito que o ajudará a evitar erros e rm *que inevitavelmente o morderá um dia.

Observe, porém, que essa localização será repetida em todos os seus subdiretórios, portanto, você pode executá-la com uma restrição de profundidade de subdiretório como esta:

find . -maxdepth 1 -name '--help' -delete

que limita a localização ao diretório atual.

aculich
fonte
Portably, você precisa fornecer finduma lista de arquivos / diretórios para examinar. Então find . -name.... -deletee -maxdepthtambém não são opções padrão.
Stéphane Chazelas
21

As respostas de Vegar Nilsen e edfuh são muito boas e as soluções adequadas para um problema como esse.

Quero adicionar uma resposta geral a esta pergunta que permita excluir qualquer arquivo com um nome de arquivo difícil. Primeiro, seu número de inode é obtido usando ls -iou alguma forma de state, em seguida, o arquivo é removido, pesquisando arquivos no diretório atual pelo número de inode e executando o rmcomando no arquivo com um número de inode correspondente

find . -inode <inode> -exec rm {}\;

Como os números de inode são exclusivos em cada sistema de arquivos, você pode remover qualquer arquivo usando isso; unicode ou usando caracteres de escape. É como é muito chato digitar, então eu recomendaria adicionar a linha

TAB: menu-complete             # Tab: Cycles through the command
"\e[Z": menu-complete-backward # Shift-Tab: Cycles backwards

no seu .inputrcarquivo se você estiver usando o bash. Isso permite que você percorra a lista de possíveis conclusões ( para mais informações ).

Baldur
fonte
5
Dessa maneira, há dois problemas: 1) não use -exec rm quando puder usar -delete; 2) obter o inode e usá-lo é desnecessariamente complicado find -name '--help' -delete
demais
Eu não acho que isso funcione. Ele percorre todos os arquivos no diretório atual e todos os seus subdiretórios, e depois de tudo o que ainda chama rm --help, o que ainda não remove o arquivo. Basta usar rm ./--help(ou rm -i *.
Keith Thompson
1
@KeithThompson findprefixa o caminho do argumento da linha de comandos para todos os arquivos, para que ele seja executado rm ./--helpe rm ./sub/dirs/--help. Para consertar o segundo, seria preciso acrescentar -maxdepth 1, mas tudo isso é essencialmente aplicar a solução do @ edfuh de uma maneira mais contundente e complicada e -deleteé mais segura do que -exec rmqualquer maneira.
jw013
1
Mais um problema com esse comando é que deve haver um espaço entre {}e \;, caso contrário, não funcionará.
22812 Eugene S
inodes podem ser únicos, mas pode haver várias entradas de diretório com o mesmo inode. Esses são chamados de hardlinks. E eles são únicos por sistema de arquivos, então você precisa usá-lo -xdev. Isso não vai ajudar você a executar isso ls -i --help.
Stéphane Chazelas
11

Uma solução brutal:

perl -e "unlink '--help' or die 'Could not unlink.';"

perl -e "rmdir '-d' or die 'Could not rmdir.';"
Thomas L Holaday
fonte
8

Passo a passo do Linux de criar um arquivo com traços e espaços e removê-lo.

SEJA CUIDADOSO! Não execute acidentalmente um rm -rf /comando de exclusão em cascata ou semelhante.

Se o arquivo que você está tentando remover incluir asteriscos ou barras, não bombeie acidentalmente um .ou /*ou *outro curinga que possa causar a exclusão do sistema operacional em cascata.

Crie um arquivo chamado "--yo yo"

eric@dev ~ $ touch -- "--yo yo"
eric@dev ~ $ ls
bin  --yo yo

Primeiro, encontre-o com find:

eric@dev ~ $ find . -name "*--yo yo*"
./--yo yo

Certifique-se de que o comando find encontre SOMENTE o arquivo ONE que você deseja excluir:

Em seguida, passe a opção -delete para encontrar e excluí-los:

eric@dev ~ $ find . -name "*--yo yo*" -delete
eric@dev ~ $ ls
bin  

Aaaannd se foi.

Eric Leschinski
fonte
2

Midnight Commander ( mc) é o mais fácil, basta apontar para ele e pressionar F8;)

Marcin
fonte
3
O OP deseja uma solução de linha de comando (CLI).
Francesco Turco
1
Midnight Commander É uma solução CLI. Basta usar o gerenciador de pacotes para instalá-lo. (Funciona até com ssh ...) pt.wikipedia.org/wiki/Midnight_Commander
daviewales 20/13
6
Como é que apt-get install mc || yum install mc; mc várias teclas de seta e F8 são mais fáceis do que rm ./--help?
Josh
3
@daviewales: O Midnight Commander é iniciado na linha de comando e é executado no terminal, mas todas as ações do teclado no Midnight Commander não são da CLI (Command Line Interface) - elas são da Midnight Commander's Interface. - Normalmente, os utilitários de linha de comando pode ser executado dentro de um script (uma exceção é a história de linha de comando bash)
Peter.O
1

aqui está uma solução que eu tinha usado antes de encontrar esta discussão.
use vimpara o diretório 'edit':

vim .

depois (no vim) selecione seu arquivo, pressione del e confirme a exclusão.
quando terminar, saia do vim com:q

atti
fonte
0

Você tentou adicionar o nome do diretório como prefixo:

$ rm ./-filename.txt dirname/-filename2.txt
$ mv ./-filename.txt filename.txt
$ cp teste ./-teste

Usar o diretório como prefixo do arquivo em geral ajuda a evitar a interpretação incorreta do caractere "menos" como uma opção de comando pela função de analisador.

Paulo Henrique Lellis Gonalves
fonte
1
Eu acredito que isso já foi abordado em uma resposta anterior .
Kusalananda
-3

Se você deseja renomear o arquivo, -.bar(mv não funcionará), tente o seguinte:

cat >foo.bar <-.bar

antes de usar o comando:

rm -- -.bar

Você deve poder examinar o conteúdo do arquivo original em foo.bar

Stephen Menasian
fonte
4
Fazer uma cópia do arquivo não é uma solução muito eficiente para renomeá-lo.
jw013
1
Você poderia usar vidir; mas isso é provavelmente tão (ou até mais) ineficiente - e muito mais perigoso.
Stephen Menasian