FreeBSD: каталог с именем ^ C (правда!) - как удалить?

127

Я сделал опечатку:

$ history
169 9:34    la /usr/local/etc/
170 9:35    sudo mkdir ^C
171 9:36    sudo mkdir /usr/local/etc/dnsmasq.d

Теперь у меня есть файл, который называется ^ C (Ctrl + C) !! Когда я использую, lsя просто вижу вопросительный знак (вероятно, из-за локали?)

% ls -al
total 60
drwxr-xr-x  2 root   wheel    512 Jan 21 09:35 ?        <- this one
drwxr-xr-x  5 admin  wheel    512 Jan 21 16:24 .
drwxr-xr-x  3 root   wheel    512 Jan 20 14:29 ..
-rw-r--r--  1 admin  nobody  1114 Jan 20 19:10 .cshrc
-rw-------  1 admin  wheel   6002 Jan 21 15:27 .history
-rw-r--r--  1 admin  nobody   182 Jan 20 14:29 .login
-rw-r--r--  1 admin  nobody    91 Jan 20 14:29 .login_conf
-rw-------  1 admin  nobody   301 Jan 20 14:29 .mail_aliases
-rw-r--r--  1 admin  nobody   271 Jan 20 19:04 .mailrc
-rw-r--r--  1 admin  nobody   726 Jan 20 19:05 .profile
-rw-------  1 admin  nobody   212 Jan 20 14:29 .rhosts
-rw-r--r--  1 admin  nobody   911 Jan 20 19:06 .shrc
drwx------  2 admin  nobody   512 Jan 20 15:05 .ssh
drwxr-xr-x  2 admin  wheel    512 Jan 20 19:08 bin

а также

% ls -i
3611537 ?   3611534 bin

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

% mv
^C/  bin/

Очевидно, я не могу набрать ^ C: - / Как мне удалить этот файл?

Mausy5043
источник
11
Жаль, что dsw не попала в POSIX.
Марк Плотник
12
@MarkPlotnick: жаль, что оригинал dsw не попал в POSIX.
Маттео Италия
4
Я не думаю, что вы назвали его ctrl + C, вы назвали его в честь символа ascii, который сопоставлен с этим сочетанием клавиш, то есть, вероятно, ETX (ascii 3). Ваш консольный шрифт не имеет глифа для этого символа, поэтому он использует общий глиф замены "?".
jiggunjer
5
emacs -nw -f diredдает каталог навигатора. <kbd> D </ kbd> удаляет файл под курсором после подтверждения.
Турбьерн Равн Андерсен
9
@MatteoItalia Это слишком плохие управляющие символы в именах файлов и других идиотских идей превратили его в POSIX ...
труба

Ответы:

188

^V( ctrl+ v) работает как своего рода escape-последовательность для следующего нажатия клавиши, вставляя связанное значение вместо выполнения любого действия, которое обычно связывается.

Используя это, ^V^C( ctrl+ v, ctrl+ c) должно работать для ввода вашего сложного имени файла в терминале.

Хокан Линдквист
источник
41
Это было, вероятно, как OP сделал их опечатку в первую очередь. V и C находятся рядом друг с другом на клавиатуре.
Стиг Хеммер
14
Или они пытались использовать буфер обмена Windows на терминале bsd.
Джоэл Коэль
2
Привычки @JoelCoel никогда не умирают!
Мафия
1
Интересно, что ^V^Cэто не работает в редакторе ЗШ линии; Виджет для вставки в кавычки (ищите страницу ^V) явно не вставляет символы прерывания. Ответ Якоба (с использованием printf) может быть более переносимым способом предоставления управляющего символа в аргументе оболочки.
Майлз
@ СтигХеммер: что также может произойти, если вы нажмете Ctrl-C в середине команды, затем забудете об этом и скопируете и вставите команду позже.
Мердад
89

Вы также можете удалить файл с помощью inode:

$ ls -i1
290742 foo
293246 ^C
$ find . -inum 293246 -delete

Что бы вы ни делали, ради бога, не ставят -deleteперед тем -inum:

$ touch foo bar baz quux
$ find . -name '*u*' -delete
$ ls
bar baz foo
$ find . -delete -name 'b*'
find: `./baz': No such file or directory
find: `./bar': No such file or directory
$ ls
$ 

Поздравляю, вы просто уничтожили все свои файлы. С find, порядок аргументов имеет значение !

епископ
источник
2
Почему бы не поставить -deleteраньше -inum? Это всего лишь мера предосторожности на случай, если вы нажмете ввод преждевременно, или порядок аргументов действительно влияет на результат?
detuur
10
@detuur: порядок влияет на результат. Смотрите редактировать.
епископ
37
Не -deleteвводите в команду точку, пока вы не запустите команду без -deleteпроверки того, что она находит то, что вы хотите.
Каз
2
@Kaz не сильно поможет с добавлением -delete в центр команды
RiaD
9
Использование @Kaz -printвместо -deleteделает очень хороший тест.
Марк Рэнсом
32

Другой вариант заключается в использовании rm -ri ./*; rmспросит вас перед удалением любого файла и каталога, поэтому вам просто нужно ответить yна «плохой» файл и nна все остальные.

На самом деле, в вашем случае вы можете даже сократить количество необходимых ответов rm -ri ./?, поскольку ваш «плохой» файл имеет длину всего один символ.

Matteo Italia
источник
8
select f in ?; do rm -i "$f"; break; doneимеет все преимущества -i, без необходимости отвечать noна ведущие нежелательные сообщения или ошибочно отвечать «да» тому, кого вы хотите оставить.
епископ
6
В случае с OP это каталог, а не файл. rmdir ?/удалит все пустые односимвольные каталоги и будет жаловаться на то, что остальные не являются пустыми.
Питер Кордес
2
@bishop: воу, я даже не знал, что selectсуществовало, довольно аккуратно!
Маттео Италия
@PeterCordes: Wops, я не заметил, что мы говорили о каталогах; Я добавил -r./- это всегда легко забыть) к своим примерам, поскольку, к сожалению rmdir, -iфлаг не поддерживается . Тем не менее, я полагаю, что в этом случае лучшим вариантом будет сочетание епископа и вашего комментария.
Matteo Italia
1
@MatteoItalia selectсуществует только в некоторых оболочках, поэтому, вероятно, вы не сталкивались с этим - скрипты и решения, предназначенные для переносимости, избегают этого, поэтому мы с меньшей вероятностью увидим это «в дикой природе».
mtraceur
23

Одним из вариантов является поиск имени файла с чем-то, кроме ls. Если вы знаете, что он был создан дословно Ctrl+ C, вы можете найти символ ASCII, созданный с использованием таблицы контрольных символов или с более дружественным интерфейсом, подобным предоставленному Python:

>>> import os
>>> os.listdir('.')
['\x03', ...]

Другим вариантом было бы посмотреть на шестнадцатеричный дамп вывода ls, используя , например hexdump.

Затем вы можете удалить файл с помощью (например) этой команды bash:

rmdir "$(printf '\x03')"

(Двойные кавычки нужны только в том случае, если символ, который вы пытаетесь вывести, находится в вашей IFSпеременной, например, \x20или \x0A, но это хорошая привычка заключать в кавычки подстановки команд, если вы не знаете, что оболочка должна выполнять разбиение полей и т. Д.)

Jakob
источник
2
Также cat -v(плюс man ascii) может помочь первая часть.
Маттео Италия
13
... или вы используете os.rmdir('\x03')прямо из оболочки Python.
moooeeeep
15

Часто в таких ситуациях легко придумать шаблон подстановки, который соответствует соответствующему файлу.

В вашем случае это было бы просто ?(сопоставление всех имен файлов точно с одним символом).

Просто убедитесь, что это действительно соответствует тому, что вы хотите:

ls -ld ?

А затем удалите каталог:

rmdir ?

Вы также можете комбинировать это с завершением вкладки . Вы можете напечатать

rmdir ?

и нажмите Tab, и, например, в Bash он будет заменен на

rmdir ^C/

и затем вы можете нажать Enter, и он сделает то, что вы хотите.

Юкка Суомела
источник
11

Вы можете использовать Midnight Commander (mc) для удаления файла - просто выберите с помощью кнопок вверх / вниз и нажмите F8.

Я делал это иногда, когда имена файлов имели странные символы из-за кодировки.

фило
источник
4
Или о любом другом файловом менеджере.
Стиг Хеммер
@StigHemmer, конечно, некоторые лучше других отображают имена файлов. Вероятно, ответ мог бы объяснить, почему MC является оптимальным выбором по сравнению с несколькими другими. Я не знал бы, поскольку я никогда не использовал это.
can-ned_food
7

Еще один способ: использовать statдля получения экранированного представления имени каталога:

$ stat *|grep File:
  File: ‘\003’

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

$ rmdir -v "$(printf '\003')"
rmdir: removing directory, ‘\003’

Или, если вы используете Bash, вы можете избежать printf:

$ rmdir -v $'\003'
rmdir: removing directory, ‘\003’
Руслан
источник
Кстати, если оболочка bash, $'\x03'это проще, чем вызывать printf. То же самое для FreeBSD sh, которая распространяется на оболочку POSIX с некоторыми вкусными функциями.
Нетч
@ Нет хороших замечаний по поводу bash $'...', но я бы вообще избежал бесполезного преобразования из восьмеричного в шестнадцатеричное. Например, что если файл был назван '\111'(на statвыходе)? Вы все еще удалили бы его, используя $'\x49'? Лучше использовать ту же последовательность , как statдал вам: в случае с ФП, в rmdir $'\003'.
Руслан
6

Решение, которое сработало для меня:

rm ./[Tab][Tab][Tab]...

циклически перебирать доступные файлы, пока не найду тот, который хочу удалить.

Но вам нужно иметь необходимые настройки в вашей оболочке, чтобы это работало.

joeytwiddle
источник
^ C действительно рано в последовательности вкладок, так что +1 для вас.
Джошудсон
5

Самый простой способ - переместить все во временный каталог, а затем rm -r DIRNAME.

Kondybas
источник
7
Вам действительно кажется это легче, чем принятый ответ?
птенцы
2
@chicks: Это на самом деле не такой плохой ответ. Я видел ^ V ^ C не работает, поэтому кто-то может застрять.
joshudson
Само по себе это не так, но кажется, что по сравнению с более прямыми решениями требуется много дополнительной работы. Может быть, я испорчен Linux, но ^vработал на меня целую вечность.
птенцы
6
@chicks ^Vнужны определенные знания, а перемещение файлов и удаление родительского каталога могут быть получены из основ.
Кондыбас
5
Ctrl + V опасно неоднозначен в зависимости от конкретной рабочей среды ... некоторые эмуляторы терминала могут интерпретировать это как вставку. Если ваш буфер вставки содержит имя чего-то, что вы не хотите удалять - и новую строку, вы можете искать проблему.
сторожевик
1

Если это единственный пустой каталог (или вы не хотите удалять другие пустые каталоги), используйтеrmdir */ . Вы получите сообщения об ошибках rmdirо невозможности удаления непустых каталогов, но это нормально. GNU rmdirподдерживает --ignore-fail-on-non-empty, или вы могли бы 2>/dev/null.

Трейлинг /заставляет глобус соответствовать только именам каталогов.

Вы можете заранее проверить, какие пустые каталоги существуют в текущем, используя
find -maxdepth 1 -type d -empty -ls. (И вы можете изменить , -lsчтобы , -deleteесли вы хотите).

Вы можете использовать более конкретное выражение glob, например, rmdir [^A-Za-z0-9._]/для сопоставления каталогов, которые начинаются с не буквенно-цифрового или подчеркивания имени файла. Я также включил ., но выражения glob .обычно не совпадают в любом случае.


Как уже отмечали другие, вы можете ограничить его односимвольными именами с помощью ?: rmdir ?/

rmdirУ него нет -iвыбора, как rm, например, потому что пустые каталоги обычно не имеют ценности и могут быть просто воссозданы.

Питер Кордес
источник
1
Вы хотели бы знать, какие каталоги вы хотите воссоздать, и rmdirможете сказать вам, если вы передадите ему -vопцию (по крайней мере, в GNU).
Руслан
@Ruslan: Нет, если у вас есть другие устаревшие каталоги, которые вам больше не нужны, и удаление их будет бонусом. Вы можете искать пустые каталоги сfind -maxdepth 1 -type d -empty -ls
Питер Кордес
-1

Прежде чем делать что-то рискованное, попробуйте сначала:

rmdir -- ^C

В общем случае - это разделитель, указывающий на команду, за которой не будет следовать ни -o ptions, но он также позволит странным символам не интерпретироваться как что-то еще.

Другой пример использования whois -r -- "-r OBJECT-RIPE"

(-r - это сокращение для спелых, но в спелых whois также параметр)

Если это не сработает с первого раза, то, возможно, попробуйте rmdir -- "^C"

Но в моей оболочке csh мне это не нужно, просто rmdir ^Cу меня уже работает.

Лео Вандев.
источник
1
В csh набирает текст с rmdir последующим <ctrl> C работает? В самом деле?! Я ожидаю, что он будет вести себя по-другому, а именно: отмена rmdirкоманды и возврат вас в командную строку.
Mausy5043
Это действительно так. Смотрите принятый ответ о том, как ввести символ ^ C в командной строке.
Ale