Comment puis-je supprimer un fichier sous Linux dont le nom ressemble à un SEUL trait d'union, comme dans «-»

33

J'ai essayé

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

Donne un coup de feu à Perl

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

...et...

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

Toute aide serait très appréciée, gens sages.

Jgrundstad
la source
Par curiosité, comment est-ce arrivé?
Petey B
2
C'était le résultat d'un wget mal construit: "wget ​​-q -O - someserver.org/s/ip "
53
Me rappelle le moment où un collègue a créé un fichier nommé *. Cette histoire ne s'est pas bien terminée.
David Heffernan
Quelle rmversion utilisez-vous ( rm --version)? rm -fonctionne bien avec GNU coreutils 8.5.
Lekensteyn
2
Une autre variante:rm ./-
un CVn

Réponses:

60

Auparavant, cela était publié dans la FAQ Usenet pour Unix. Je vois que cela se trouve dans la FAQ de l'utilitaire GNU Core Utility . Il y avait au moins cinq méthodes différentes, mais cela fonctionne bien:

$ rm ./-

Si un nom de fichier contient des caractères non typables, utilisez:

$ rm -i *

L' -iindicateur demande une confirmation pour chaque fichier s'il doit être supprimé ou non.

Wallyk
la source
1
Ou rm -i - ' - ' si vous recherchez des fichiers contenant un tiret et peut-être des espaces ou autre chose.
Hans-Peter Störr
1
rm -i * a également travaillé pour moi. Merci wallyk!
Jgrundstad
39

La suppression d'un fichier dont le nom commence par -est une FAQ, mais il semble que vous ayez un problème différent.

Parmi les solutions que vous avez mentionnées dans la question:

rm -- -

Cela devrait fonctionner.

rm "-"

Ce n'est pas différent de rm -. Les guillemets sont supprimés par le shell et la rmcommande ne considère que le trait d'union comme un argument. Les guillemets sont utiles pour échapper aux métacaractères du shell; le trait d'union est spécial pour rm, pas à la coquille.

rm "\-"

Les guillemets échappent à la barre oblique inversée. Cette action tente donc de supprimer un fichier dont le nom est composé de deux caractères, une barre oblique inversée et un trait d'union.

rm \-

C'est comme rm "-", équivalent à rm -.

En fait, du moins avec la version GNU coreutils de rm, rm -supprime (ou tente de supprimer) un fichier dont le nom se compose uniquement d’un trait d’union. Si votre fichier avait ce nom, il serait déjà parti. Je conclus que votre fichier a un nom qui ressemble à un trait d'union.

ls | cat -A

devrait donner une idée de ce que ça s'appelle vraiment.

Voici un script Perl que je viens de rassembler pour vous demander d'indiquer chaque fichier du répertoire en cours et de vous demander si vous souhaitez le supprimer. Offert sans garantie, mais je l'ai testé brièvement.

#!/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 : Une solution moins élaborée: si le nom du fichier n’est qu’un caractère, il rm ?convient de le supprimer (ainsi que tout autre fichier de ce type).

Keith Thompson
la source
13
M-bM-^@M-^Sest une représentation de la représentation UTF-8 à 3 octets du caractère Unicode "EN DASH", 0x2013. Je me demande si vous l'avez accidentellement copié-collé à partir d'une page Web.
Keith Thompson
7
n'a rm -i *pas fonctionné? On dirait que cela ferait la même chose que le script Perl.
user606723
2
Je suppose que cela provient de la page Web sur laquelle j'ai pointé le wget. En tout cas, merci encore pour la solution complète! prends soin.
jgrundstad
5
perl -e 'unlink grep {print "remove $ _?"; <STDIN> = ~ / y / i} glob "*" '
Randal Schwartz
6
@ RandalSchwartz: Impressionnant, laconique (et fait mal à mon cerveau) - mais je voudrais /^y/iplutôt que /y/i. Après tout, un utilisateur russe peut taper "Nyet".
Keith Thompson
19

Si vous voulez quelque chose de plus sûr ...

Essayez d’utiliser une combinaison de ls et find (cela fonctionne pour tout fichier que vous êtes autorisé à supprimer).

Le paramètre '-i' vous donnera le numéro d'inode pour chaque entrée de répertoire ls -li

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

Une fois que vous avez le numéro d'inode ...

find . -inum **27** -exec rm -i {} \;
Sam
la source
2
+1 car c'est une excellente réponse générale à ces problèmes. Soit dit en passant, il n'est pas nécessaire d'utiliser -exec rm dans les recherches récentes, il suffit d'utiliser -delete
Sirex
2
@Sirex - Je pense que le but -exec rm -i {}est -ide demander la suppression. Je regarde man findet ne vois aucun moyen de faire cela.
Stephen P
oh oui, dans ce cas. était plus d'un pourboire.
Sirex
13

Donnez rm ./-un essai.

Le -est un drapeau pour commencer un argument de drapeau. Si vous commencez l'argument avec autre chose qu'un -, dans ce cas /, le nom de fichier sera supposé. Quel est ce que vous souhaitez.

Et puisque fileet ./filesont le même fichier, il ciblera le fichier nommé -via ./-.

Petey B
la source
8
Plutôt que de taper 30 caractères, il aurait peut-être été plus utile d'expliquer pourquoi le / aide à analyser correctement
Ivo Flipse
@ gcb Merci pour l'édition proposée. J'y ai ajouté du balisage de code pour qu'il soit plus facile à lire.
Slhck
7

Pas aussi geek que la plupart des autres réponses, mais je voudrais lancer une instance de mc, commandant de minuit, et juste sélectionner et supprimer le fichier.

johanvdw
la source
+1 pour contourner intelligemment le problème - et cela sans même recourir à un programme d'interface graphique.
Sleske
7

Essayer:

$ ls -b

pour voir si le nom de fichier contient des caractères non imprimables.

Noel Yap
la source
Pourquoi le vote négatif? Compte tenu du suivi , cela semble être une très bonne suggestion.
Ilmari Karonen
6

Non pas qu'il soit nécessaire d'utiliser perl ici, mais cela devrait fonctionner:

perl -e 'unlink "-"'

ou pour voir quelle erreur avec ce qui précède pourrait être:

perl -e 'unlink "-" or die "Err: $!"'
coureur
la source
Cette méthode présente l'avantage de ne pas s'inquiéter des caractères spéciaux (autres que les problèmes de guillemets).
Kevin Reid
3

J'ai eu de la chance en utilisant Nautilus de GNOME pour supprimer des fichiers mal nommés. Utilisez-vous un serveur X? Je suis sûr que d'autres navigateurs de fichiers fonctionneraient aussi.

Joel Berger
la source
3

Si

rm -- -

n'a pas fonctionné, le nom du fichier n'est pas "juste un trait d'union". Si aucun autre fichier ne contient un trait d'union, vous pouvez essayer

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

Jusqu'à présent, je reçois un "Aucun fichier ou répertoire de ce type" pour chaque méthode publiée jusqu'à présent:

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

Il semble que j'ai rm version 7.4. Je vais essayer de mettre à jour et de réessayer ces suggestions. Merci à tous pour votre aide.

Jgrundstad
la source
1
J'imagine qu'il n'existe aucun fichier ou répertoire de ce type et que le nom du fichier contient peut-être également des caractères invisibles. (et vous pourriez avoir à peu près le même message d'erreur en Perl avec 'unlink "- ou die" Err: $! "'). Essayez "ls -b" pour voir quel est le vrai nom de fichier.
runrig
1

J'aime beaucoup utiliser le diredmode dans emacs pour ce genre de choses - il suffit d'ouvrir le répertoire dans emacs. Vous pouvez facilement sélectionner des fichiers et les marquer pour suppression.

Une autre affiche a suggéré d'utiliser le commandant de minuit; c'est à peu près la même idée, mais si vous êtes déjà un utilisateur d'Emacs, c'est peut-être plus pratique.

Ernest Friedman-Hill
la source
0

Devrait pouvoir faire a rm -f '-'travaillé pour moi dans cygwin

D'ailleurs, rm -semble également fonctionner sur le chapeau rouge.

Lucas
la source
dans Ubuntu: ~ / jj $ rm -rf '-' ~ / jj $ ls -
rm -travaille pour moi aussi.
Uzsolt
1
Pourquoi -r? Demander une suppression récursive si vous n'en avez pas besoin est toujours dangereux en cas de mauvaise saisie.
Hans-Peter Störr
@hstoerr, bon point. juste habbit. les mains tapent plus vite que le cerveau. retouche maintenant, merci.
Lucas