FreeBSD: Diretório chamado ^ C (realmente!) - como remover?

127

Eu cometi um erro de digitação:

$ history
169 9:34    la /usr/local/etc/
170 9:35    sudo mkdir ^C
171 9:36    sudo mkdir /usr/local/etc/dnsmasq.d

Agora eu tenho um arquivo chamado ^ C (ctrl + C) !! Quando uso, lsvejo apenas um ponto de interrogação (provavelmente devido à localidade?)

% ls -al
total 60
drwxr-xr-x  2 root   wheel    512 Jan 21 09:35 ?        <- this one
drwxr-xr-x  5 admin  wheel    512 Jan 21 16:24 .
drwxr-xr-x  3 root   wheel    512 Jan 20 14:29 ..
-rw-r--r--  1 admin  nobody  1114 Jan 20 19:10 .cshrc
-rw-------  1 admin  wheel   6002 Jan 21 15:27 .history
-rw-r--r--  1 admin  nobody   182 Jan 20 14:29 .login
-rw-r--r--  1 admin  nobody    91 Jan 20 14:29 .login_conf
-rw-------  1 admin  nobody   301 Jan 20 14:29 .mail_aliases
-rw-r--r--  1 admin  nobody   271 Jan 20 19:04 .mailrc
-rw-r--r--  1 admin  nobody   726 Jan 20 19:05 .profile
-rw-------  1 admin  nobody   212 Jan 20 14:29 .rhosts
-rw-r--r--  1 admin  nobody   911 Jan 20 19:06 .shrc
drwx------  2 admin  nobody   512 Jan 20 15:05 .ssh
drwxr-xr-x  2 admin  wheel    512 Jan 20 19:08 bin

e

% ls -i
3611537 ?   3611534 bin

Eu quero remover este arquivo Eu tento mve ao usar o preenchimento de guias, ele me mostra:

% mv
^C/  bin/

Obviamente não consigo digitar ^ C: - / Como removo este arquivo?

Mausy5043
fonte
11
É uma pena que o dsw não tenha entrado no POSIX.
Mark Plotnick
12
@ MarkPlotnick: pena que o original dsw não chegou ao POSIX.
Matteo Italia
4
Eu não acho que você o nomeou ctrl + C, você o nomeou após o caractere ascii que é mapeado para o atalho de teclado, ou seja, provavelmente ETX (ascii 3). A fonte do console não possui glifo para esse caractere, portanto, usa um glifo de substituição genérico "?".
jiggunjer
5
emacs -nw -f diredfornece um navegador de diretório. <kbd> D </kbd> exclui o arquivo sob o cursor após a confirmação.
Thorbjørn Ravn Andersen
9
@MatteoItalia É caracteres de controle muito ruim em nomes de arquivos e outros idiotas idéias tornou em POSIX ...
tubo de

Respostas:

188

^V( ctrl+ v) funciona como um tipo de sequência de escape para o próximo pressionamento de tecla, inserindo o valor associado em vez de executar qualquer ação que normalmente seria associada.

Fazendo uso disso, ^V^C( ctrl+ v, ctrl+ c) deve funcionar para inserir seu nome de arquivo difícil no terminal.

Håkan Lindqvist
fonte
41
Provavelmente foi assim que o OP fez seu erro de digitação em primeiro lugar. V e C estão bem próximos um do outro no teclado.
Stig Hemmer
14
Ou eles estavam tentando usar a área de transferência do Windows no terminal bsd.
Joel Coel
2
Os hábitos @JoelCoel nunca morrem!
Mafii 24/01
11
Curiosamente, ^V^Cse não trabalhar no editor de linha Zsh; o widget de inserção entre aspas (pesquise na página ^V) explicitamente não insere caracteres de interrupção. A resposta de Jakob (usando printf) pode ser uma maneira mais portátil de fornecer um caractere de controle em um argumento shell.
Miles
@StigHemmer: O que também pode acontecer é que você pressione Ctrl-C no meio de um comando, esqueça isso e copie e cole o comando mais tarde.
Mehrdad 29/01
89

Você também pode remover o arquivo por inode:

$ ls -i1
290742 foo
293246 ^C
$ find . -inum 293246 -delete

O que quer que você faça, pelo amor de Deus, não coloque -deleteantes -inum:

$ touch foo bar baz quux
$ find . -name '*u*' -delete
$ ls
bar baz foo
$ find . -delete -name 'b*'
find: `./baz': No such file or directory
find: `./bar': No such file or directory
$ ls
$ 

Parabéns, você acabou de apagar todos os seus arquivos. Com find, a ordem dos argumentos importa !

bispo
fonte
2
Por que não colocar -deleteantes -inum? Isso é apenas uma precaução no caso de você pressionar Enter prematuramente ou a ordem dos argumentos realmente afeta o resultado?
detuur
10
@detuur: ordem afeta o resultado. Veja editar.
bispo
37
Não insira -deleteo comando, ponto final, até que você execute o comando sem -deleteverificar se ele está encontrando o que deseja.
Kaz 23/01
2
@Kaz não vai ajudar muito com a adição de -delete no centro de comando
Riad
9
@Kaz usando em -printvez de -deletefaz um teste muito bom.
Mark Ransom
32

Outra opção é usar rm -ri ./*; rmperguntará antes de excluir qualquer arquivo e diretório, então você só precisa responder yao arquivo "ruim" e na todos os outros.

Na verdade, no seu caso, você pode até reduzir o número de respostas necessárias rm -ri ./?, pois seu arquivo "ruim" tem apenas um caractere.

Matteo Italia
fonte
8
select f in ?; do rm -i "$f"; break; donetem todos os benefícios de -i, sem a agonia de ter que responder noa liderar indesejáveis ​​ou responder erroneamente sim àquele que você deseja manter.
bispo
6
No caso do OP, é um diretório, não um arquivo. rmdir ?/removerá todos os diretórios vazios de um caractere e reclamará que os outros não estejam vazios.
Peter Cordes
2
@ bispo: uau, eu nem sabia que selectexistia, muito legal!
Matteo Italia
@ PeterCordes: wops, eu não percebi que estávamos falando sobre diretórios; Adicionei -r(e ./- é sempre fácil esquecer) aos meus exemplos, pois infelizmente rmdirnão suporta a -ibandeira. Ainda assim, suponho que, neste caso, o melhor caminho a seguir seria uma combinação de bispo e seu comentário.
Matteo Italia
11
O @MatteoItalia selectexiste apenas em alguns shells, e é provavelmente por isso que você não os encontrou - scripts e soluções que devem ser portáteis evitam-no, por isso é menos provável que o vejamos "em estado selvagem".
Mtraceur
23

Uma opção é procurar o nome do arquivo com algo diferente de ls. Se você souber que foi produzido por um verbatim Ctrl+ C, poderá encontrar o caractere ASCII produzido usando uma tabela de caracteres de controle ou com uma interface mais amigável como a fornecida pelo Python:

>>> import os
>>> os.listdir('.')
['\x03', ...]

Outra opção seria olhar para um dump hexadecimal da saída de ls, usando, por exemplo hexdump.

Em seguida, você pode excluir o arquivo com (por exemplo) este comando bash:

rmdir "$(printf '\x03')"

(As aspas duplas são necessárias apenas se o caractere que você está tentando imprimir estiver em sua IFSvariável, como \x20ou \x0A, mas é um bom hábito citar substituições de comandos, a menos que você saiba que deseja que o shell realize a divisão de campos etc.)

Jakob
fonte
2
Também cat -v(mais man ascii) pode ajudar na primeira parte.
Matteo Italia
13
... ou você usa os.rmdir('\x03')diretamente do shell Python.
moooeeeep
15

Geralmente, nesse tipo de situação, é fácil criar um padrão curinga que corresponda ao arquivo relevante.

No seu caso, isso seria simples ?(combinando todos os nomes de arquivos com exatamente um caractere).

Basta verificar se realmente corresponde ao que você deseja:

ls -ld ?

E, em seguida, remova o diretório:

rmdir ?

Você também pode combinar isso com a conclusão da guia . Você pode digitar

rmdir ?

e pressione tab e, por exemplo, no bash será substituído por

rmdir ^C/

e você pode pressionar enter e ele faz o que deseja.

Jukka Suomela
fonte
11

Você pode usar o Midnight Commander (mc) para excluir o arquivo - basta selecionar com os botões para cima / para baixo e pressionar F8.

Fiz isso ocasionalmente quando os nomes de arquivos tinham caracteres estranhos devido à codificação.

filo
fonte
4
Ou qualquer outro gerenciador de arquivos.
Stig Hemmer
@StigHemmer, é claro, alguns se saem melhor do que outros por exibir determinados nomes de arquivos. Provavelmente, a resposta poderia explicar por que o MC é uma escolha ideal em comparação com alguns outros selecionados. Eu não saberia, porque nunca o usei.
pode-ned_food
7

Ainda de outra maneira: use statpara obter uma representação escapada do nome do diretório:

$ stat *|grep File:
  File: ‘\003’

Agora você conhece uma representação do nome do arquivo, para poder removê-lo pelo nome usando printf:

$ rmdir -v "$(printf '\003')"
rmdir: removing directory, ‘\003’

Ou, se você estiver usando o bash, poderá evitar printf:

$ rmdir -v $'\003'
rmdir: removing directory, ‘\003’
Ruslan
fonte
BTW, se o shell é bash, $'\x03'é mais simples do que chamar printf. O mesmo para o FreeBSD sh que é estendido sobre o shell POSIX com alguns recursos interessantes.
Netch 28/01
@ Busque um bom argumento sobre o bash $'...', mas evitaria a conversão inútil de octal para hexadecimal em geral. Por exemplo, e se o arquivo tiver sido nomeado '\111'(na statsaída)? Você ainda o removeria usando $'\x49'? Melhor usar a mesma sequência que statvocê forneceu: no caso do OP rmdir $'\003',.
Ruslan
6

Uma solução que funcionou para mim é:

rm ./[Tab][Tab][Tab]...

para percorrer os arquivos disponíveis até encontrar o que quero remover.

Mas você precisa ter as configurações necessárias no seu shell para que isso funcione.

joeytwiddle
fonte
^ C é realmente o início da sequência de guias, então +1 para você.
Joshudson
5

A maneira mais fácil é mover tudo para o diretório temporário e depois rm -r DIRNAME.

Kondybas
fonte
7
Isso realmente parece mais fácil para você do que a resposta aceita?
pintainhos
2
@chicks: Na verdade, não é uma resposta tão ruim. Eu vi ^ V ^ C não funcionar, para que alguém possa ficar preso.
joshudson
Não está errado por si só, mas parece muito trabalho extra em comparação com as soluções mais diretas. Talvez eu seja mimado pelo Linux, mas ^vtrabalhe consistentemente comigo há séculos.
pintainhos
6
Os @chicks ^Vprecisam de um conhecimento específico, enquanto mover arquivos e a remoção do diretório pai pode ser derivada do básico.
Kondybas
5
Ctrl + V é perigosamente ambíguo, dependendo do seu ambiente de trabalho exato ... alguns emuladores de terminal podem interpretá-lo como uma pasta. Se o seu buffer de colagem contiver o nome de algo que você não deseja excluir - e uma nova linha, você poderá estar procurando um problema.
rackandboneman
1

Se for o único diretório vazio (ou você não se importa em remover outros diretórios vazios), usermdir */ . Você receberá mensagens de erro rmdirsobre não conseguir remover diretórios não vazios, mas tudo bem. O GNU rmdirsuporta --ignore-fail-on-non-empty, ou você poderia 2>/dev/null.

A trilha /faz com que o glob corresponda apenas aos nomes de diretório.

Você pode verificar com antecedência quais diretórios vazios existem no diretório atual usando
find -maxdepth 1 -type d -empty -ls. (E você pode mudar -lspara -deletese quiser).

Você pode usar uma expressão glob mais específica como rmdir [^A-Za-z0-9._]/corresponder aos diretórios que começam com um nome de arquivo não alfanumérico ou sublinhado. Também incluí ., mas as expressões glob não coincidem .normalmente.


Como outros já apontaram, você pode limitá-lo a nomes de caracteres únicos com um globo de ?: rmdir ?/

rmdirnão tem uma -iopção do jeito que rmtem, provavelmente porque diretórios vazios geralmente não são valiosos e podem ser recriados.

Peter Cordes
fonte
11
Você gostaria de saber quais diretórios deseja recriar e rmdirpode dizer se você passa a -vopção para ele (pelo menos no GNU).
Ruslan
@Ruslan: Não, se você tivesse outros diretórios obsoletos com os quais não se importava mais, e removê-los seria um bônus. Você pode olhar para os diretórios vazios comfind -maxdepth 1 -type d -empty -ls
Peter Cordes
-1

Antes de fazer algo arriscado, tente primeiro:

rmdir -- ^C

Em geral - é um delimitador dizendo ao comando que não haverá opções, mas também permitirá que caracteres estranhos não sejam interpretados como outra coisa.

Outro exemplo de uso é whois -r -- "-r OBJECT-RIPE"

(-r é um atalho para maduro, mas no maduro também é um parâmetro)

Se não funcionar na primeira tentativa, talvez tente rmdir -- "^C"

Mas no meu shell csh não preciso disso, simplesmente rmdir ^Cjá funciona para mim.

Leo Vandew.
fonte
11
Na digitação csh rmdir seguida de <ctrl> C funciona? Realmente?! Eu esperaria que ele se comportasse de maneira diferente, ou seja, abortando o rmdircomando e retornando você à linha de comando.
precisa saber é o seguinte
Será mesmo. Veja a resposta aceita sobre como inserir um caracter ^ C na linha de comando.
Ale