Як видалити файл в Linux, ім'я якого виглядає так, що це ТІЛЬКИ дефіс, як у "-"


33

Я намагався

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

Дав Перлу постріл

~$ 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

Будь-яка допомога буде дуже вдячна, мудрі люди.


З цікавості, як це дісталося?
Petey B

2
Це було результатом погано побудованого wget: "wget ​​-q -O - someserver.org/s/ip "

53
Нагадує про той час, коли колега створив файл на ім’я *. Ця історія не закінчилася добре.
Девід Геффернан

Яку rmверсію ви використовуєте ( rm --version)? rm -прекрасно працює з GNU coreutils 8.5.
Лекенштейн

2
Ще один варіант:rm ./-
CVn

Відповіді:


60

Це було розміщено у FAQs Usenet для Unix - я бачу, що це поширені запитання про основні утиліти GNU . Існувало щонайменше п’ять різних методів, але це добре працює:

$ rm ./-

Якщо ім'я файлу містить неперевірені символи, тоді використовуйте:

$ rm -i *

-iПрапор запитує підтвердження для кожного файлу , якщо вона повинна бути вилучена чи ні.


1
Або rm -i - ' - ', якщо ви шукаєте файли, що містять тире та, можливо, пробіли чи що завгодно.
Ганс-Пітер Штерр

1
rm -i * теж працював на мене. Дякую wallyk!
jgrundstad

39

Видалення файлу, з імен якого починається, -- це FAQ, але, схоже, у вас є інша проблема.

З рішень, які ви згадали у запитанні:

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;
    }
}

EDIT : Менш продумане рішення: якщо ім'я файлу є лише одним символом, його rm ?слід видалити (разом з будь-якими іншими такими файлами).


13
M-bM-^@M-^Sявляє собою 3-байтове представлення UTF-8 символу Unicode "EN DASH", 0x2013. Цікаво, чи випадково ви скопіювали і вставили його з веб-сторінки.
Кіт Томпсон

7
нічого rm -i *не працює? Здається, це зробить те саме, що і сценарій perl.
користувач606723

2
Я здогадуюсь, що вона походить із веб-сторінки, на яку я вказав на wget. У будь-якому випадку, ще раз дякую за ретельне рішення! піклуватися.
jgrundstad

5
perl -e 'від’єднати grep {print "видалити $ _?"; <STDIN> = ~ / y / i} glob "*" '
Рандаль Шварц

6
@RandalSchwartz: Вражаюче короткий (і змушує мого мозку трохи боліти) - але я хотів би /^y/iскоріше, ніж /y/i. Зрештою, російський користувач може набрати "Nyet".
Кіт Томпсон

19

Якщо ви хочете чогось безпечнішого ...

Спробуйте скористатися комбінацією ls і знайти (це працює для будь-якого файлу, у якого ви маєте дозвіл на видалення)

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

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

Після отримання номера inode ...

find . -inum **27** -exec rm -i {} \;

2
+1, оскільки це чудова загальна відповідь на ці проблеми. До речі, немає необхідності використовувати -exec rm в останніх знахідках, просто використовуйте -delete
Sirex

2
@Sirex - Я думаю, що сенс -exec rm -i {}полягає у запиті -iна видалення. Я дивлюсь man findі не бачу ніякого способу зробити це.
Stephen P

о так, у цьому випадку. була більше підказка.
Сірекс

13

Дайте rm ./-спробувати.

Це -прапор для початку аргументу прапора. Якщо ви запускаєте аргумент із чогось іншого, а не -, у цьому випадку /він вважатиме, що це ім'я файлу. Що ви хочете.

А оскільки fileі ./fileтой самий файл, він буде націлений на файл, названий -через ./-.


8
Замість того, щоб набрати 30 символів, можливо, було б корисніше пояснити, чому / допомагає правильно розбирати
Іво Фліпс

@gcb Дякуємо за запропоновану редакцію. Я додав до цього розмітку коду, щоб було легше читати.
slhck

7

Не настільки вигадливий, як більшість інших відповідей, але я б запустив екземпляр команди mc, опівночі, і просто виберіть і видаліть файл.


+1 за вміле побічне вирішення проблеми - і це, навіть не вдаючись до програми GUI.
sleske


6

Не те, що тут слід використовувати perl, але це має працювати:

perl -e 'unlink "-"'

або щоб побачити, яка може бути будь-яка помилка із зазначеним вище:

perl -e 'unlink "-" or die "Err: $!"'

Перевага цього методу полягає в тому, що немає спеціальних символів, про які слід турбуватися (крім питань цитування рядків).
Кевін Рейд

3

Мені пощастило скористатися Nautilus GNOME для видалення файлів з поганою назвою. У вас працює X-сервер? Я впевнений, що працюватимуть і інші файлові браузери.


3

Якщо

rm -- -

не працювало, ім'я файлу не "лише дефіс". Якщо жоден з інших файлів не містить дефіса, ви можете спробувати

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

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. Я спробую оновити та повторно спробувати ці пропозиції. Дякую всім за допомогу.


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 -працює і для мене.
узсольт

1
Чому -r? Запит рекурсивного видалення, якщо він вам не потрібен, це завжди небезпечно у випадку зловживань.
Ганс-Пітер Стрер

@hstoerr, хороший момент. просто звикання. руки набирають швидше, ніж мозок. редагування відповіді зараз, дякую.
Лукас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.