¿Cómo elimino un archivo cuyo nombre comienza con "-" (guión también conocido como guión o menos)?

349

¿Cómo se elimina un archivo cuyo nombre de archivo comienza con un guión (guión o menos) -? Estoy en un servidor OSX remoto y tengo este archivo en mi directorio:

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

¿Cómo en el mundo puedo eliminar --helpde una CLI? Este problema es algo que encuentro en diferentes formas en ocasiones, estos archivos son fáciles de crear, pero difíciles de eliminar.

He intentado usar la barra invertida

rm \-\-help

He intentado citas

rm "--help"

¿Cómo evito que el carácter menos (guión o guión) se interprete como una opción?

Bryan Rehbein
fuente
1
Sería genial si se cambiara el nombre de esta pregunta a "Cómo eliminar un archivo cuyo nombre comienza con -".
Sandy
@Sandy estuvo de acuerdo; Normalmente no me gusta cambiar el significado de una pregunta, pero en este caso la respuesta aceptada es específica para este problema
Michael Mrozek
33
Me parece un poco irónico que en rm --helprealidad explica cómo eliminar nombres de archivos que comienzan con a -. Buena pregunta, sin embargo.
lesmana
1
@ jw013 A veces, la ayuda es fácil de entender para los usuarios experimentados, pero abrumadora y confusa para los novatos.
iconoclasta
1
Me encontré con esto en un sistema usando rm de BusyBox. Todo es mínimo, incluida la ayuda, por lo que rm --help no proporcionó ninguna pista.
dslake

Respuestas:

497

Use "-" para hacer que rm deje de analizar las opciones de la línea de comandos, como esta:

rm -- --help
Vegar Nilsen
fuente
1
Sabía que era algo muy simple como esto ...
Bryan Rehbein
2
¿Todas las versiones del rmcomando admiten el --argumento?
Keith Thompson
3
@KeithThompson: es una característica de la mayoría de las herramientas GNU, por lo que no funcionará en la mayoría de los Unix'es que no sean GNU ("no Linux") (por ejemplo, variantes BSD o algunos sistemas integrados)
dtech
1
¡GRACIAS! Eso me salvó el día. ¡Y, por supuesto, funciona en BSD (OSX) y con otros comandos!
raskhadafi
8
@dtech, getopt () y --anterior a GNU (SysIII, 1980) y son estándar / POSIX. Utilidades estándar, excepto por algunas excepciones (como echo) entienden --. YMMV para otros comandos si no usan la API getopt () para analizar las opciones.
Stéphane Chazelas
214

O puedes hacer

rm ./--help
edfuh
fuente
77
No es que importe, pero esto parece lo más "apropiado".
James M.
2
Este es el que recuerdo. Usar "rm - --help" es algo que siempre tengo que buscar.
user603
25
Este método siempre funciona incluso para comandos que no se tratan --especialmente.
jw013
Y también trabaja para evitar un tratamiento especial por parte de algunos comandos para otros tipos (al lado de las opciones) de los argumentos con nombres especiales como el -de los servicios públicos o de texto cd, el foo=barde awk...
Stéphane Chazelas
1
Esto funciona cuando un archivo comienza con un solo guión, donde rm -- <filename>no lo hizo.
StockB
37

Use findpara hacerlo:

find . -name '--help' -delete

Y este es un buen método porque si tiene más de unos pocos archivos como este que puede eliminar, puede obtener una lista de vista previa de los archivos simplemente ejecutando find sin la -deleteopción primero, y luego, si la lista de archivos se ve bien, simplemente ejecute de nuevo con -delete.

De hecho, evitar rma favor find(especialmente con la vista previa primero) es un buen hábito que lo ayudará a evitar errores rm *que inevitablemente lo morderán algún día.

Tenga en cuenta, sin embargo, que find se repetirá en todos sus subdirectorios, por lo que es posible que desee ejecutarlo con una restricción de profundidad de subdirectorio como esta:

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

que limita la búsqueda al directorio actual.

aculich
fuente
Portablemente, debe proporcionar finduna lista de archivos / directorios para examinar. Por lo tanto find . -name.... -deletey -maxdepthtampoco son opciones estándar.
Stéphane Chazelas
21

Las respuestas de Vegar Nilsen y edfuh son muy buenas y las soluciones adecuadas para un problema como este.

Quiero agregar una respuesta general a esta pregunta que le permita eliminar cualquier archivo con un nombre de archivo difícil. Primero se obtiene su número de inodo utilizando ls -io de alguna forma staty luego se elimina el archivo buscando archivos en el directorio actual por número de inodo y ejecutando el rmcomando en el archivo con un número de inodo coincidente

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

Dado que los números de inodo son únicos en cada sistema de archivos, puede eliminar cualquier archivo con esto; Unicode o utilizando caracteres de escape. Es muy molesto escribir, así que recomendaría agregar la línea

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

en tu .inputrcarchivo si estás usando bash. Esto le permite recorrer la lista de posibles finalizaciones ( para obtener más información ).

Baldur
fuente
55
De esta manera tiene dos problemas: 1) no use -exec rm cuando pueda usar -delete; 2) obtener el inodo y usarlo es innecesariamente complicado cuando solo puede usar:find -name '--help' -delete
aculich
No creo que eso funcione. Atraviesa todos los archivos en el directorio actual y todos sus subdirectorios, y después de todo eso aún invoca rm --help, que aún no eliminará el archivo. Simplemente use rm ./--help(o rm -i *.
Keith Thompson
1
@KeithThompson findprefija la ruta del argumento de la línea de comando a todos los archivos, para que se ejecute rm ./--helpy rm ./sub/dirs/--help. Para arreglar el segundo, uno tendría que agregar -maxdepth 1, pero todo esto es esencialmente aplicar la solución de @ edfuh de una manera más indirecta y enrevesada, y -deletees más seguro que de -exec rmtodos modos.
jw013
1
Un problema más con este comando es que debe haber un espacio entre ellos {}y \;, de lo contrario, no funcionará.
Eugene S
Los inodes pueden ser únicos pero puede haber varias entradas de directorio con el mismo inodo. Esos se llaman enlaces duros. Y solo son únicos por sistema de archivos, por lo que deberá usarlos -xdev. Eso no te ayudará a ejecutar eso ls -i --help.
Stéphane Chazelas
11

Una solución brutal:

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

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

Tutorial de Linux para crear un archivo con guiones y espacios, luego eliminarlo.

¡TEN CUIDADO! No ejecute accidentalmente un rm -rf /comando de eliminación en cascada o similar.

Si el archivo que está intentando quitar incluye asteriscos o barras, no bombee un accidente .o /*o *o algún otro comodín que podría conectar en cascada eliminar su sistema operativo.

Crea un archivo llamado "--yo yo"

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

Primero, encuéntralo con find:

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

Asegúrese de que el comando de búsqueda SOLO encuentre el archivo ONE que desea eliminar:

Luego pase la opción -delete para buscar, para eliminarlos:

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

Aaaannd se ha ido.

Eric Leschinski
fuente
2

Midnight Commander ( mc) es el más fácil, solo apúntalo y presiona F8;)

Marcin
fuente
3
El OP quiere una solución de línea de comando (CLI).
Francesco Turco
1
Midnight Commander ES una solución CLI. Simplemente use su administrador de paquetes para instalarlo. (Incluso funciona sobre ssh ...) en.wikipedia.org/wiki/Midnight_Commander
daviewales
66
¿Cómo es más fácil que apt-get install mc || yum install mc; mc varias teclas de flecha y F8rm ./--help ?
Josh
3
@daviewales: Midnight Commander se inicia desde la línea de comandos y se ejecuta en la terminal, pero todas las acciones de teclado dentro de Midnight Commander no son de la CLI (interfaz de línea de comandos), sino de la interfaz de Midnight Commander. - Por lo general, las utilidades de línea de comando se pueden ejecutar dentro de un script (una excepción es el historial de línea de comando bash)
Peter.O
1

Aquí hay una solución que había usado antes de encontrar este hilo.
utilizar vimpara 'editar' directorio:

vim .

luego (en vim) seleccione su archivo, presione Supr y confirme la eliminación.
cuando hayas terminado, deja vim con:q

atti
fuente
0

¿Has intentado agregar el nombre del directorio como prefijo:

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

El uso del directorio como prefijo del archivo en general ayuda a evitar que la función del analizador interprete incorrectamente el carácter "menos" como una opción de comando.

Paulo Henrique Lellis Gonalves
fuente
1
Creo que esto ya estaba cubierto en una respuesta anterior .
Kusalananda
-3

Si desea cambiar el nombre del archivo, -.bar(mv no funcionará), intente esto:

cat >foo.bar <-.bar

antes de usar el comando:

rm -- -.bar

Debería poder examinar el contenido del archivo original en foo.bar

Stephen Menasian
fuente
44
Hacer una copia del archivo no es una solución muy eficiente para renombrarlo.
jw013
1
Podrías usar vidir; pero eso es probablemente tan (o incluso más) ineficiente, y mucho más peligroso.
Stephen Menasian