FreeBSD: Katalog o nazwie ^ C (naprawdę!) - jak usunąć?

127

Zrobiłem literówkę:

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

Teraz mam plik o nazwie ^ C (ctrl + C) !! Kiedy używam ls, po prostu widzę znak zapytania (prawdopodobnie z powodu ustawień regionalnych?)

% 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

i

% ls -i
3611537 ?   3611534 bin

Chcę usunąć ten plik. Próbuję, mva przy użyciu uzupełniania tabulatorów pokazuje mi:

% mv
^C/  bin/

Oczywiście nie mogę wpisać ^ C: - / Jak usunąć ten plik?

Mausy5043
źródło
11
Szkoda, że dsw nie dostało się do POSIX.
Mark Plotnick
12
@MarkPlotnick: szkoda, że oryginał dsw nie przeszedł na POSIX.
Matteo Italia
4
Nie sądzę, że nazwałeś go ctrl + C, nazwałeś go po znaku ascii, który jest odwzorowany na ten skrót klawiaturowy, tj. Prawdopodobnie ETX (ascii 3). Czcionka konsoli nie ma żadnego glifu dla tego znaku, więc używa ogólnego glifu podstawienia „?”.
jiggunjer
5
emacs -nw -f direddaje nawigator katalogów. <kbd> D </kbd> usuwa plik pod kursorem po potwierdzeniu.
Thorbjørn Ravn Andersen
9
@MatteoItalia To zbyt złe znaki kontrolne w nazwach plików i inne idiotyczne pomysły trafiły do POSIX ...
pipe

Odpowiedzi:

188

^V( ctrl+ v) działa jako rodzaj sekwencji ucieczki dla następnego naciśnięcia klawisza, wstawiając powiązaną wartość zamiast wykonywania czynności, które normalnie byłyby powiązane.

Korzystając z tego, ^V^C( ctrl+ v, ctrl+ c) powinien działać, aby wprowadzić trudną nazwę pliku w terminalu.

Håkan Lindqvist
źródło
41
Prawdopodobnie w ten sposób OP zrobiło literówkę. V i C znajdują się obok siebie na klawiaturze.
Stig Hemmer
14
Lub próbowali użyć schowka Windows na terminalu bsd.
Joel Coel
2
@JoelCoel nawyki nigdy nie umierają!
Mafii
1
Co ciekawe, ^V^Cma nie pracować w edytorze linii zsh; quoted-insert widget (przeszukać stronę dla ^V) wyraźnie nie wstawić znaki przerwań. Odpowiedź Jakoba (za pomocą printf) może być bardziej przenośnym sposobem dostarczenia znaku kontrolnego w argumencie powłoki.
Miles
@StigHemmer: Możesz również nacisnąć Ctrl-C w środku polecenia, a następnie zapomnieć o tym i skopiować i wkleić polecenie później.
Mehrdad
89

Możesz także usunąć plik za pomocą i-węzła:

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

Cokolwiek robicie, na miłość boską, nie stawiajcie -deleteprzedtem -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
$ 

Gratulacje, właśnie wyczyściłeś wszystkie swoje pliki. Z find, kolejność argumentów ma znaczenie !

biskup
źródło
2
Dlaczego nie postawić -deletewcześniej -inum? Czy to tylko środek ostrożności w przypadku przedwczesnego naciśnięcia klawisza Enter lub kolejność argumentów faktycznie wpływa na wynik?
detuur
10
@detuur: kolejność wpływa na wynik. Zobacz edycję.
biskup
37
Nie wpisuj -deletepolecenia, kropka, dopóki nie uruchomisz polecenia bez -deletesprawdzenia, czy znajduje to, czego szukasz.
Kaz
2
@Kaz niewiele pomoże w dodaniu -delete w centrum dowodzenia
RiaD
9
Używanie @Kaz -printzamiast -deleterobi bardzo dobry test.
Mark Ransom,
32

Inną opcją jest użycie rm -ri ./*; rmzapyta cię przed usunięciem dowolnego pliku i katalogu, więc musisz tylko odpowiedzieć yna „zły” plik i nna wszystkie pozostałe.

W rzeczywistości możesz nawet zmniejszyć liczbę potrzebnych odpowiedzi rm -ri ./?, ponieważ „zły” plik ma tylko jeden znak.

Matteo Italia
źródło
8
select f in ?; do rm -i "$f"; break; donema wszystkie zalety -i, bez męki polegającej na tym, że trzeba odpowiadać nona wiodące działania niepożądane lub omyłkowo odpowiadać tak na osobę, którą chcesz zatrzymać.
biskup
6
W przypadku OP jest to katalog, a nie plik. rmdir ?/usunie wszystkie puste katalogi jednoznakowe i narzeka, że ​​inne nie są puste.
Peter Cordes
2
@bishop: whoa, nawet nie wiedziałem, że selectistnieje, całkiem fajnie!
Matteo Italia,
@PeterCordes: wops, nie zauważyłem, że rozmawiamy o katalogach; Dodałem -r(i ./- zawsze łatwo zapomnieć) do moich przykładów, ponieważ niestety rmdirnie obsługuje -iflagi. Przypuszczam jednak, że w tym przypadku najlepszym rozwiązaniem będzie połączenie wypowiedzi biskupa i twojego komentarza.
Matteo Italia,
1
@MatteoItalia selectistnieje tylko w niektórych powłokach, prawdopodobnie dlatego go nie spotkałeś - skrypty i rozwiązania, które mają być przenośne, unikają go, więc mniej prawdopodobne jest, że zobaczymy go „na wolności”.
mtraceur
23

Jedną z opcji jest sprawdzenie nazwy pliku za pomocą czegoś innego niż ls. Jeśli wiesz, że został stworzony przez verbatim Ctrl+ C, możesz znaleźć znak ASCII utworzony przy użyciu tabeli znaków kontrolnych lub z bardziej przyjaznym interfejsem, takim jak ten zapewniany przez Python:

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

Inną opcją byłoby przyjrzenie się zrzutowi szesnastkowemu wyniku ls, używając np hexdump.

Następnie możesz usunąć plik za pomocą (na przykład) tego polecenia bash:

rmdir "$(printf '\x03')"

(Podwójne cudzysłowy są potrzebne tylko wtedy, gdy znak, który próbujesz wydrukować, znajduje się w IFSzmiennej, takiej jak \x20lub \x0A, ale dobrym zwyczajem jest cytowanie podstawień poleceń, chyba że wiesz, że chcesz, aby powłoka wykonywała podział pola itp.)

Jakob
źródło
2
Również cat -v(plus man ascii) może pomóc w pierwszej części.
Matteo Italia
13
... lub używasz os.rmdir('\x03')bezpośrednio z powłoki Python.
moooeeeep
15

Często w tego rodzaju sytuacjach łatwo jest znaleźć wzór wieloznaczny pasujący do odpowiedniego pliku.

W twoim przypadku byłoby to po prostu ?(dopasowanie wszystkich nazw plików z dokładnie jednym znakiem).

Po prostu sprawdź, czy naprawdę pasuje do tego, co chcesz:

ls -ld ?

A następnie usuń katalog:

rmdir ?

Możesz także połączyć to z uzupełnianiem tabulatorów . Możesz pisać

rmdir ?

i naciśnij tab, i np. w bash zostanie zastąpiony przez

rmdir ^C/

a następnie możesz nacisnąć Enter i robi to, co chcesz.

Jukka Suomela
źródło
11

Możesz użyć Midnight Commander (mc), aby usunąć plik - po prostu wybierz za pomocą przycisków góra / dół i naciśnij F8.

Robiłem to czasami, gdy nazwy plików miały dziwne znaki z powodu kodowania.

filo
źródło
4
Lub prawie jakikolwiek inny menedżer plików.
Stig Hemmer
@StigHemmer, oczywiście, niektórzy radzą sobie lepiej niż inni pod względem wyświetlania niektórych nazw plików. Prawdopodobnie odpowiedź mogłaby wyjaśnić, dlaczego MC jest optymalnym wyborem w porównaniu z kilkoma wybranymi innymi. Nie wiedziałbym, bo nigdy go nie użyłem.
can-ned_food
7

Jeszcze inny sposób: użyj, stataby uzyskać ucieczkową reprezentację nazwy katalogu:

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

Teraz znasz reprezentację nazwy pliku, dzięki czemu możesz usunąć plik według nazwy, używając printf:

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

Lub, jeśli używasz bash, możesz uniknąć printf:

$ rmdir -v $'\003'
rmdir: removing directory, ‘\003’
Ruslan
źródło
BTW, jeśli powłoka jest bash, $'\x03'jest prostsze niż wywołanie printf. To samo dotyczy sh FreeBSD, który jest rozszerzony na powłokę POSIX z kilkoma smakowitymi funkcjami.
Netch
@ Pobierz dobrą rację na temat basha $'...', ale ogólnie unikałbym bezużytecznej konwersji z ósemkowej na szesnastkową. Np. Co jeśli plik zostałby nazwany '\111'( statwyjściowy)? Czy nadal byś go usunął za pomocą $'\x49'? Lepiej wykorzystywać tę samą sekwencję jak statdał ci: w przypadku PO za, rmdir $'\003'.
Ruslan
6

Rozwiązaniem, które zadziałało dla mnie jest:

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

cyklicznie przeglądać dostępne pliki, aż znajdę ten, który chcę usunąć.

Ale aby to działało, musisz mieć niezbędne ustawienia w swojej powłoce.

joeytwiddle
źródło
^ C jest naprawdę wcześnie w sekwencji tabulatorów, więc +1 dla Ciebie.
joshudson
5

Najprostszym sposobem jest przeniesienie wszystkiego do katalogu tymczasowego, a następnie rm -r DIRNAME.

Kondybas
źródło
7
Czy to naprawdę wydaje ci się łatwiejsze niż zaakceptowana odpowiedź?
pisklęta
2
@ chicks: Właściwie to nie jest taka zła odpowiedź. Widziałem, że ^ V ^ C nie działa, więc ktoś może utknąć.
joshudson
Nie jest to samo w sobie złe, ale wydaje się, że to dużo dodatkowej pracy w porównaniu do bardziej bezpośrednich rozwiązań. Być może Linux mnie rozpieszcza, ale ^vod wieków działał konsekwentnie.
pisklęta
6
@ pisklęta ^Vpotrzebują konkretnej wiedzy podczas przenoszenia plików, a usunięcie katalogu nadrzędnego można uzyskać z podstaw.
Kondybas
5
Ctrl + V jest niebezpiecznie niejednoznaczny w zależności od konkretnego środowiska pracy ... niektóre emulatory terminali mogą interpretować to jako pastę. Jeśli bufor wklejania zawiera nazwę czegoś, czego nie chcesz usuwać - i nowy wiersz, możesz patrzeć na problem.
rackandboneman
1

Jeśli jest to jedyny pusty katalog (lub nie obchodzi Cię usuwanie innych pustych katalogów), użyjrmdir */ . Otrzymasz komunikaty o błędach z rmdirpowodu niemożności usunięcia niepustych katalogów, ale to w porządku. GNU rmdirobsługuje --ignore-fail-on-non-empty, a ty możesz 2>/dev/null.

Końcowe /powoduje, że glob pasuje tylko do nazw katalogów.

Możesz z góry sprawdzić, które puste katalogi istnieją w bieżącym za pomocą
find -maxdepth 1 -type d -empty -ls. (I można zmienić -ls, aby -delete, jeśli chcesz).

Można użyć bardziej szczegółowego wyrażenia glob, na przykład rmdir [^A-Za-z0-9._]/do dopasowania katalogów rozpoczynających się od niealfanumerycznej lub podkreślonej nazwy pliku. Uwzględniłem również ., ale wyrażenia glob i tak nie pasują .normalnie.


Jak zauważyli inni, możesz ograniczyć je do nazw jednoznakowych za pomocą globu ?: rmdir ?/

rmdirnie ma takiej -iopcji rm, prawdopodobnie dlatego, że puste katalogi zwykle nie są cenne i można je po prostu odtworzyć.

Peter Cordes
źródło
1
Chcesz wiedzieć, które katalogi chcesz odtworzyć, i rmdirmożesz powiedzieć, czy podasz -vopcję (przynajmniej w GNU).
Ruslan
@ Ruslan: Nie, jeśli miałbyś inne przestarzałe katalogi, o które już Ci nie chodziło, a usunięcie ich byłoby bonusem. Możesz szukać pustych katalogów zfind -maxdepth 1 -type d -empty -ls
Peter Cordes
-1

Zanim zrobisz coś ryzykownego, spróbuj najpierw:

rmdir -- ^C

Ogólnie rzecz biorąc - jest separatorem informującym, że polecenie nie będzie wykonywane, ale pozwoli także na interpretowanie dziwnych znaków jako czegoś innego.

Innym przykładem użycia jest whois -r -- "-r OBJECT-RIPE"

(-r jest skrótem dla dojrzałych, ale u dojrzałych whois również parametr)

Jeśli to nie działa przy pierwszej próbie, może spróbuj rmdir -- "^C"

Ale w mojej powłoce csh nie potrzebuję jej, po prostu rmdir ^Cjuż działa dla mnie.

Leo Vandew.
źródło
1
W wpisywaniu w csh rmdir następuje <ctrl> C działa? Naprawdę?! Spodziewałbym się, że zachowa się inaczej, a mianowicie przerwie rmdirpolecenie i powróci do linii poleceń.
Mausy5043
Rzeczywiście tak będzie. Zobacz zaakceptowaną odpowiedź na temat wprowadzania znaku ^ C w wierszu polecenia.
Ale