Как удалить файл в Linux, имя которого выглядит ТОЛЬКО дефисом, как в «-»

33

я пробовал

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

Дал Perl выстрел

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

...а также...

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

Любая помощь будет высоко ценится, мудрые люди.

jgrundstad
источник
Из любопытства, как он туда попал?
Пити Б.
2
Это был результат плохо сконструированного wget: "wget ​​-q -O - someserver.org/s/ip "
53
Напоминает мне о времени, когда коллега создал файл с именем *. Эта история не закончилась хорошо.
Дэвид Хеффернан
Какую rmверсию вы используете ( rm --version)? rm -отлично работает с GNU coreutils 8.5.
Лекенштейн
2
Другой вариант:rm ./-
CVN

Ответы:

60

Раньше это было опубликовано в часто задаваемых вопросах Usenet для Unix - я вижу, что это в часто задаваемых вопросах по GNU Core Utility . Было как минимум пять разных методов, но это хорошо работает:

$ rm ./-

Если имя файла содержит нетипизируемые символы, используйте:

$ rm -i *

-iФлаг запрашивает подтверждение для каждого файла , если она должна быть удалена или нет.

wallyk
источник
1
Или rm -i - ' - ', если вы ищете файлы, содержащие тире и, возможно, некоторые пробелы или что-то еще.
Ханс-Петер Стёрр,
1
У меня тоже работал. Спасибо, Wallyk!
Jgrundstad
39

Удаление файла, чьи имена начинаются с, -- это часто задаваемые вопросы, но похоже, что у вас другая проблема.

Из решений, которые вы упомянули в вопросе:

rm -- -

Это должно работать.

rm "-"

Это ничем не отличается от rm -. Кавычки отбрасываются оболочкой, и rmкоманда просто видит один дефис в качестве аргумента. Кавычки полезны для экранирования метасимволов оболочки; дефис является особенным rm, а не оболочкой.

rm "\-"

Кавычки экранируют обратную косую черту, поэтому при попытке удалить файл, имя которого состоит из двух символов, обратной косой черты и дефиса.

rm \-

Это так же, как rm "-", эквивалентно rm -.

Как это происходит, по крайней мере в версии GNU coreutils rm, rm -фактически удаляет (или пытается удалить) файл, имя которого состоит только из дефиса. Если бы у вашего файла было это имя, оно уже исчезло бы. Я делаю вывод, что у вашего файла есть имя, которое выглядит только как дефис.

ls | cat -A

должен дать представление о том, что это на самом деле называется.

Вот сценарий Perl, который я только что скомбинировал, который подскажет вам для каждого файла в текущем каталоге и спросит, нужно ли его удалить. Предлагается без гарантии, но я проверил это вкратце.

#!/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;
    }
}

РЕДАКТИРОВАТЬ : менее сложное решение: если имя файла только один символ, то rm ?следует удалить его (вместе с любыми другими такими файлами).

Кит Томпсон
источник
13
M-bM-^@M-^Sпредставляет собой 3-байтовое представление UTF-8 символа Unicode "EN DASH", 0x2013. Интересно, вы случайно скопировали и вставили его с веб-страницы?
Кит Томпсон
7
ничего rm -i *не работает? Похоже, он будет делать то же самое, что и скрипт perl.
user606723
2
Я предполагаю, что это произошло от веб-страницы, на которую я указал Wget. В любом случае, еще раз спасибо за тщательное решение! Береги себя.
jgrundstad
5
perl -e 'unlink grep {print "remove $ _?"; <STDIN> = ~ / y / i} glob "*" '
Рэндал Шварц
6
@RandalSchwartz: Впечатляюще лаконично (и немного болит мозг) - но я бы /^y/iпредпочел, чем /y/i. В конце концов, русский пользователь может напечатать "Nyet".
Кит Томпсон
19

Если вы хотите что-то более безопасное ...

Попробуйте использовать комбинацию ls и find (это работает для любого файла, который вы можете удалить)

Параметр '-i' даст вам номер инода для каждой записи каталога ls -li

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

Как только у вас есть номер инода ...

find . -inum **27** -exec rm -i {} \;
Сэм
источник
2
+1, так как это отличный общий ответ на эти проблемы. Кстати, в последних поисках нет необходимости использовать -exec rm, просто используйте -delete
Sirex
2
@Sirex - я думаю, что смысл в -exec rm -i {}том, -iчтобы запросить удаление. Я смотрю man findи не вижу никакого способа сделать это.
Стивен П
о да, в этом случае. было больше чаевых.
Sirex
13

Дай rm ./-попробовать.

-Представляет собой флаг , чтобы начать аргумент флага. Если вы начинаете аргумент с чего-либо, кроме a -, в этом случае /он будет считать, что это имя файла. Что ты хочешь?

А так как fileи ./fileявляются одним и тем же файлом, он будет нацелен на файл с именем -via ./-.

Пити Б
источник
8
Вместо того, чтобы вводить 30 символов, возможно, было бы более полезно объяснить, почему / помогает правильно анализировать
Ivo Flipse
@gcb Спасибо за предложенное редактирование. Я добавил к этому разметку кода, чтобы было легче читать.
Slhck
7

Не такой отвратительный, как большинство других ответов, но я бы запустил экземпляр mcMidnight Commander и просто выбрал и удалил файл.

johanvdw
источник
+1 за умный обход проблемы - и это даже не прибегая к программе GUI.
Слеське
7

Пытаться:

$ ls -b

чтобы увидеть, есть ли в имени файла непечатаемые символы.

Ноэль Яп
источник
Почему отрицательный голос? Учитывая продолжение , это звучит как очень хорошее предложение.
Илмари Каронен
6

Не то чтобы здесь нужно было использовать perl, но это должно работать:

perl -e 'unlink "-"'

или посмотреть, что может быть любой ошибкой с вышеперечисленным:

perl -e 'unlink "-" or die "Err: $!"'
Runrig
источник
Преимущество этого метода в том, что не нужно беспокоиться о специальных символах (кроме проблем со строковыми кавычками).
Кевин Рид
3

Мне повезло, используя GNOME Nautilus для удаления плохо названных файлов. Вы используете X-сервер? Я уверен, что другие файловые браузеры тоже будут работать.

Джоэл Бергер
источник
3

Если

rm -- -

не работает, имя файла не "просто дефис". Если в других файлах нет дефиса, попробуйте

perl -E'for (@_) { if (/-/) { unlink($_) or die $! } }' -- *
Ikegami
источник
1

Пока что я получаю «Нет такого файла или каталога» для каждого метода, опубликованного до сих пор:

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

Похоже, у меня есть версия 7.4. Я постараюсь обновить и повторить эти предложения. Спасибо всем за помощь.

jgrundstad
источник
1
Я предполагаю, что нет такого файла или каталога, и, возможно, имя файла также содержит некоторые невидимые символы. (и вы можете получить примерно такое же сообщение об ошибке в perl с помощью 'unlink' - "или die" Err: $! "'). Попробуйте "ls -b", чтобы увидеть реальное имя файла.
runrig
1

Я очень люблю использовать diredрежим в Emacs для такого рода вещей - просто "открыть" каталог в Emacs. Вы можете легко выбрать файлы и пометить их для удаления.

Другой плакат предложил использовать полуночного командира; это почти та же идея, но если вы уже являетесь пользователем emacs, возможно, это более удобно.

Эрнест Фридман-Хилл
источник
0

Должен быть в состоянии сделать rm -f '-'работал для меня в Cygwin

В этом отношении, rm -также, кажется, работает над красной шляпой.

Лукас
источник
в Ubuntu: ~ / jj $ rm -rf '-' ~ / jj $ ls -
rm -у меня тоже работает.
uzsolt
1
Почему -r? Запрос рекурсивного удаления, если он вам не нужен, всегда опасен в случае неправильного написания.
Ганс-Петер Стёрр,
@hstoerr, хорошая мысль. просто привычка. руки печатают быстрее, чем мозг. редактирование ответа сейчас, спасибо.
Лукас