¿Cómo elimino un archivo en Linux cuyo nombre parece SOLO un guión, como en "-"

33

He intentado

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

Le dio un tiro a Perl

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

...y...

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

Cualquier ayuda sería muy apreciada, amigos sabios.

jgrundstad
fuente
Por curiosidad, ¿cómo llegó allí?
Petey B
2
Fue el resultado de un wget mal construido: "wget ​​-q -O - someserver.org/s/ip "
53
Me recuerda a la vez que un colega creó un archivo llamado *. Esta historia no terminó bien.
David Heffernan
¿Qué rmversión estás usando ( rm --version)? rm -funciona bien con GNU coreutils 8.5.
Lekensteyn
2
Otra variante:rm ./-
un CVn

Respuestas:

60

Esto solía publicarse en las preguntas frecuentes de Usenet para Unix; veo que está en las preguntas frecuentes de GNU Core Utility . Había al menos cinco métodos diferentes, pero esto funciona bien:

$ rm ./-

Si un nombre de archivo contiene caracteres que no se pueden escribir, use:

$ rm -i *

La -ibandera solicita confirmación para cada archivo si debe eliminarse o no.

wallyk
fuente
1
O rm -i - ' - ' si está buscando archivos que contengan un guión y tal vez algunos espacios o lo que sea.
Hans-Peter Störr
1
rm -i * también funcionó para mí. Gracias wallyk!
jgrundstad
39

Eliminar un archivo cuyos nombres comienzan con -es una pregunta frecuente, pero parece que tienes un problema diferente.

De las soluciones que mencionó en la pregunta:

rm -- -

Eso debería funcionar.

rm "-"

Eso no es diferente de rm -. El shell elimina las comillas, y el rmcomando solo ve el guión simple como un argumento. Las comillas son útiles para escapar de metacaracteres de shell; el guión es especial para rm, no para la concha.

rm "\-"

Las comillas escapan de la barra diagonal inversa, por lo que intenta eliminar un archivo cuyo nombre consta de dos caracteres, una barra diagonal inversa y un guión.

rm \-

Esto es igual rm "-", equivalente a rm -.

De hecho, al menos con la versión de GNU coreutils rm, en rm -realidad elimina (o intenta eliminar) un archivo cuyo nombre consiste solo en un guión. Si su archivo tuviera ese nombre, ya se habría ido. Concluyo que su archivo tiene un nombre que solo parece un guión.

ls | cat -A

debería dar una idea de cómo se llama realmente.

Aquí hay un script de Perl que acabo de crear que le pedirá cada archivo en el directorio actual y le preguntará si desea eliminarlo. Se ofrece sin garantía, pero lo probé 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;
    }
}

EDITAR : Una solución menos elaborada: si el nombre del archivo es solo un carácter, rm ?debería eliminarlo (junto con cualquier otro archivo de este tipo).

Keith Thompson
fuente
13
M-bM-^@M-^Ses una representación de la representación UTF-8 de 3 bytes del carácter "EN DASH" de Unicode, 0x2013. Me pregunto si accidentalmente lo copiaste y lo pegaste desde una página web.
Keith Thompson
77
hizo rm -i *que no funcione? Parece que haría lo mismo que el script perl.
user606723
2
Supongo que se originó en la página web a la que apunté el wget. En cualquier caso, ¡gracias de nuevo por la solución completa! Cuídate.
jgrundstad
55
perl -e 'unlink grep {print "remove $ _?"; <STDIN> = ~ / a / i} glob "*" '
Randal Schwartz
66
@RandalSchwartz: Impresionantemente breve (y me duele un poco el cerebro), pero me gustaría /^y/imás que eso /y/i. Después de todo, un usuario ruso podría escribir "Nyet".
Keith Thompson
19

Si quieres algo más seguro ...

Intente usar una combinación de ls y find (esto funciona para cualquier archivo que tenga permiso para eliminar)

El parámetro '-i' le dará el número de inodo para cada entrada de directorio ls -li

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

Una vez que tenga el número de inodo ...

find . -inum **27** -exec rm -i {} \;
Sam
fuente
2
+1 ya que esta es una gran respuesta general para estos problemas. Por cierto, no hay necesidad de usar -exec rm en hallazgos recientes, solo use -delete
Sirex
2
@Sirex: creo que el objetivo -exec rm -i {}es -isolicitar la eliminación. Estoy mirando man findy no veo ninguna forma de hacerlo.
Stephen P
oh si, en este caso. fue más de una propina.
Sirex
13

Darle rm ./-una oportunidad.

El -es un indicador para iniciar un argumento de indicador. Si comienza el argumento con cualquier cosa que no sea a -, en este caso /, asumirá que es el nombre del archivo. Que es lo que deseas.

Y puesto filey ./fileson el mismo archivo, que se dirigirá el archivo llamado -vía ./-.

Petey B
fuente
8
En lugar de escribir 30 caracteres, quizás hubiera sido más útil explicar por qué / ayuda a analizar correctamente
Ivo Flipse
@gcb Gracias por la edición propuesta. Agregué marcado de código a eso, por lo que sería más fácil de leer.
slhck
7

No es tan geek como la mayoría de las otras respuestas, pero activaría una instancia de mc, comandante de medianoche, y simplemente seleccionaría y eliminaría el archivo.

johanvdw
fuente
+1 para esquivar el problema de forma inteligente, y eso sin siquiera recurrir a un programa GUI.
sleske
7

Tratar:

$ ls -b

para ver si el nombre del archivo tiene caracteres no imprimibles.

Noel Yap
fuente
¿Por qué el voto negativo? Dado el seguimiento , esto suena como una muy buena sugerencia.
Ilmari Karonen
6

No es que sea necesario usar perl aquí, pero esto debería funcionar:

perl -e 'unlink "-"'

o para ver cuál podría ser cualquier error con lo anterior:

perl -e 'unlink "-" or die "Err: $!"'
runrig
fuente
Este método tiene la ventaja de que no hay caracteres especiales de los que preocuparse (aparte de los problemas de comillas).
Kevin Reid
3

He tenido suerte usando Nautilus de GNOME para eliminar archivos mal nombrados. ¿Estás ejecutando un servidor X? Estoy seguro de que otros navegadores de archivos también funcionarían.

Joel Berger
fuente
3

Si

rm -- -

no funcionó, el nombre del archivo no es "solo un guión". Si ningún otro archivo tiene un guión, puede intentar

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

Hasta ahora recibo un "No existe tal archivo o directorio" para cada método publicado hasta ahora:

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 tengo la versión rm 7.4. Intentaré actualizar y volver a intentar estas sugerencias. Gracias a todos por ayudar.

jgrundstad
fuente
1
Supongo que no existe tal archivo o directorio, y tal vez el nombre del archivo también contiene algunos caracteres invisibles. (y podría obtener el mismo mensaje de error en perl con 'desvincular "-" o morir "Err: $!"'). Pruebe "ls -b" para ver cuál es el nombre real del archivo.
runrig
1

Soy muy aficionado al uso del diredmodo en emacs para este tipo de cosas: simplemente "abra" el directorio en emacs. Puede seleccionar fácilmente archivos y marcarlos para eliminarlos.

Otro cartel sugería usar el comandante de medianoche; esta es más o menos la misma idea, pero si ya eres usuario de emacs quizás sea más conveniente.

Ernest Friedman-Hill
fuente
0

Debería poder rm -f '-'trabajar para mí en Cygwin

Para el caso, rm -también parece funcionar en Red Hat.

Lucas
fuente
en Ubuntu: ~ / jj $ rm -rf '-' ~ / jj $ ls -
rm -A mí también me funciona.
uzsolt
1
¿Por qué -r? Solicitar una eliminación recursiva si no la necesita siempre es peligroso en caso de errores ortográficos.
Hans-Peter Störr
@hstoerr, buen punto. solo habito. Las manos escriben más rápido que el cerebro. Respuesta de edición ahora, gracias.
Lucas