FreeBSD: Direktori bernama ^ C (sungguh!) - cara menghapus?

127

Saya salah ketik:

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

Sekarang saya punya file yang disebut ^ C (ctrl + C) !! Ketika saya menggunakan lssaya hanya melihat tanda tanya (mungkin karena lokal?)

% 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

dan

% ls -i
3611537 ?   3611534 bin

Saya ingin menghapus file ini. Saya mencoba mvdan ketika menggunakan penyelesaian tab itu menunjukkan kepada saya:

% mv
^C/  bin/

Jelas saya tidak bisa mengetikkan ^ C: - / Bagaimana cara menghapus file ini?

Mausy5043
sumber
11
Sayang sekali dsw tidak berhasil menjadi POSIX.
Mark Plotnick
12
@MarkPlotnick: sayang sekali yang asli dsw tidak membuatnya menjadi POSIX.
Matteo Italia
4
Saya tidak berpikir Anda menamainya ctrl + C, Anda menamainya setelah karakter ascii yang dipetakan ke pintasan keyboard itu, yaitu ETX (ascii 3) mungkin. Font konsol Anda tidak memiliki glyph untuk karakter itu, jadi ia menggunakan glyph substitusi generik "?".
jiggunjer
5
emacs -nw -f diredmemberikan navigator direktori. <kbd> D </kbd> menghapus file di bawah kursor setelah konfirmasi.
Thorbjørn Ravn Andersen
9
@MatteoItalia Karakter kontrol yang terlalu buruk dalam nama file dan ide idiot lainnya membuatnya menjadi POSIX ...
pipe

Jawaban:

188

^V( ctrl+ v) berfungsi sebagai semacam urutan pelepasan untuk penekanan tombol berikutnya, memasukkan nilai yang terkait alih-alih mengambil tindakan apa pun yang biasanya dikaitkan.

Memanfaatkan ini, ^V^C( ctrl+ v, ctrl+ c) harus bekerja untuk memasukkan nama file Anda yang sulit di terminal.

Håkan Lindqvist
sumber
41
Ini mungkin bagaimana OP membuat kesalahan ketik mereka di tempat pertama. V dan C berada tepat di samping satu sama lain di keyboard.
Stig Hemmer
14
Atau mereka mencoba menggunakan clipboard Windows di terminal bsd.
Joel Coel
2
Kebiasaan @ JoelCoel tidak pernah mati!
Mafii
1
Menariknya, ^V^Ctidak tidak bekerja dalam editor garis Zsh; yang dikutip-insert widget (mencari halaman untuk ^V) secara eksplisit tidak memasukkan karakter interupsi. Jawaban Jakob (menggunakan printf) mungkin cara yang lebih portabel untuk memasok karakter kontrol dalam argumen shell.
Miles
@ StigHemmer: Apa yang juga bisa terjadi adalah Anda menekan Ctrl-C di tengah-tengah perintah, lalu lupakan ini dan salin-tempel perintah nanti.
Mehrdad
89

Anda juga dapat menghapus file dengan inode:

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

Apa pun yang Anda lakukan, demi Tuhan, jangan menempatkan -deletesebelumnya -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
$ 

Selamat, Anda baru saja menghapus semua file Anda. Dengan find, urutan argumen penting !

uskup
sumber
2
Mengapa tidak menempatkan -deletesebelumnya -inum? Apakah ini hanya tindakan pencegahan jika Anda menekan enter sebelum waktunya atau apakah urutan argumen benar-benar mempengaruhi hasilnya?
detuur
10
@detuur: pesanan memengaruhi hasil. Lihat edit.
Uskup
37
Jangan masukkan -deleteperintah, titik, sampai Anda menjalankan perintah tanpa -deletememeriksa apakah itu menemukan apa yang Anda inginkan.
Kaz
2
@Kaz tidak akan banyak membantu dengan menambahkan -delete di pusat komando
RiaD
9
@Kaz menggunakan -printbukan -deletemembuat tes yang sangat bagus.
Mark Ransom
32

Pilihan lain adalah menggunakan rm -ri ./*; rmakan bertanya kepada Anda sebelum menghapus file dan direktori apa pun, jadi Anda hanya perlu membalas yfile "buruk", dan nsemua yang lain.

Sebenarnya, dalam kasus Anda, Anda bahkan dapat mengurangi jumlah balasan yang diperlukan dengan melakukan rm -ri ./?, karena file "buruk" Anda hanya satu karakter.

Matteo Italia
sumber
8
select f in ?; do rm -i "$f"; break; donememiliki semua manfaat -i, tanpa kesulitan harus menjawab nountuk memimpin yang tidak diinginkan atau salah menjawab ya untuk orang yang ingin Anda pertahankan.
Uskup
6
Dalam kasus OP itu adalah direktori, bukan file. rmdir ?/akan menghapus semua direktori karakter tunggal yang kosong, dan mengeluh tentang yang lain tidak kosong.
Peter Cordes
2
@ bishop: whoa, aku bahkan tidak tahu itu selectada, cukup rapi!
Matteo Italia
@PeterCordes: wops, saya tidak memperhatikan bahwa kita berbicara tentang direktori; Saya menambahkan -r(dan ./- selalu mudah untuk melupakan) ke contoh saya, karena sayangnya rmdirtidak mendukung -ibendera. Tetap saja, saya kira dalam hal ini cara terbaik untuk pergi adalah kombinasi dari uskup dan komentar Anda.
Matteo Italia
1
@MatteoItalia selecthanya ada di beberapa shell, yang mungkin mengapa Anda belum menemukan itu - skrip dan solusi yang dimaksudkan untuk portabel menghindarinya, jadi kami cenderung melihatnya "di alam liar".
mtraceur
23

Salah satu opsi adalah mencari nama file dengan sesuatu selain ls. Jika Anda tahu itu diproduksi oleh Ctrl+ kata demi kata C, Anda dapat menemukan karakter ASCII yang diproduksi menggunakan tabel karakter kontrol , atau dengan antarmuka yang lebih ramah seperti yang disediakan oleh Python:

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

Pilihan lain adalah melihat dump hex output ls, menggunakan mis hexdump.

Kemudian Anda dapat menghapus file dengan (misalnya) perintah bash ini:

rmdir "$(printf '\x03')"

(Kutipan ganda hanya diperlukan jika karakter yang Anda coba cetak ada dalam IFSvariabel Anda , seperti \x20atau \x0A, tapi itu kebiasaan yang baik untuk mengutip pergantian perintah kecuali Anda tahu Anda ingin shell untuk melakukan pemisahan bidang, dll.)

Jakob
sumber
2
Juga cat -v(plus man ascii) dapat membantu untuk bagian pertama.
Matteo Italia
13
... atau Anda gunakan os.rmdir('\x03')langsung dari shell Python.
moooeeeep
15

Seringkali dalam situasi seperti ini mudah untuk menghasilkan pola wildcard yang cocok dengan file yang relevan.

Dalam kasus Anda, ini hanya ?(mencocokkan semua nama file dengan tepat satu karakter).

Hanya periksa apakah itu benar-benar cocok dengan yang Anda inginkan:

ls -ld ?

Dan kemudian hapus direktori:

rmdir ?

Anda juga dapat menggabungkan ini dengan penyelesaian tab . Anda bisa mengetik

rmdir ?

dan tekan tab, dan misalnya dalam bash itu akan digantikan oleh

rmdir ^C/

dan Anda kemudian dapat menekan enter dan itu melakukan apa yang Anda inginkan.

Jukka Suomela
sumber
11

Anda dapat menggunakan Midnight Commander (mc) untuk menghapus file - cukup pilih dengan tombol atas / bawah dan tekan F8.

Saya melakukannya sesekali ketika nama file memiliki karakter aneh karena penyandian.

filo
sumber
4
Atau hampir semua pengelola file lainnya.
Stig Hemmer
@ StigHemmer tentu saja, beberapa melakukan lebih baik daripada yang lain untuk menampilkan nama file tertentu. Mungkin jawabannya bisa menjelaskan mengapa MC adalah pilihan yang optimal dibandingkan dengan beberapa yang lain. Saya tidak akan tahu, karena saya tidak pernah menggunakannya.
can-ned_food
7

Namun cara lain: gunakan statuntuk mendapatkan representasi yang lolos dari nama direktori:

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

Sekarang Anda tahu representasi dari nama file, sehingga Anda dapat menghapus file dengan nama menggunakan printf:

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

Atau, jika Anda menggunakan bash, Anda dapat menghindari printf:

$ rmdir -v $'\003'
rmdir: removing directory, ‘\003’
Ruslan
sumber
BTW jika shellnya bash, $'\x03'lebih sederhana daripada memanggil printf. Hal yang sama untuk FreeBSD sh yang diperluas pada shell POSIX dengan beberapa fitur lezat.
Netch
@Note bagus tentang bash $'...', tapi saya akan menghindari konversi yang tidak berguna dari oktal ke heksadesimal secara umum. Misalnya bagaimana jika file tersebut dinamai '\111'(dalam statoutput)? Apakah Anda masih menghapusnya menggunakan $'\x49'? Lebih baik gunakan urutan yang sama seperti statmemberi Anda: dalam kasus OP rmdir $'\003',.
Ruslan
6

Solusi yang berhasil bagi saya adalah:

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

untuk menggilir file yang tersedia sampai saya menemukan yang ingin saya hapus.

Tetapi Anda perlu memiliki pengaturan yang diperlukan di shell Anda agar bisa berfungsi.

joeytwiddle
sumber
^ C benar-benar awal dalam urutan tab jadi +1 untuk Anda.
joshudson
5

Cara termudah adalah memindahkan semuanya ke direktori sementara lalu rm -r DIRNAME.

Kondybas
sumber
7
Apakah ini benar-benar lebih mudah bagi Anda daripada jawaban yang diterima?
anak ayam
2
@ Chicks: Ini sebenarnya bukan jawaban yang buruk. Saya telah melihat ^ V ^ C tidak bekerja sehingga seseorang mungkin macet.
joshudson
Itu tidak salah, tetapi sepertinya banyak pekerjaan ekstra dibandingkan dengan solusi yang lebih langsung. Mungkin saya dimanjakan oleh Linux, tetapi ^vtelah bekerja secara konsisten sejak lama.
anak ayam
6
@chicks ^Vmemerlukan pengetahuan khusus saat memindahkan file dan menghapus direktori induk dapat diturunkan dari dasar-dasar.
Kondybas
5
Ctrl + V sangat berbahaya, tergantung pada lingkungan kerja Anda yang tepat ... beberapa emulator terminal dapat menafsirkannya sebagai tempel. Jika buffer paste Anda berisi nama sesuatu yang tidak ingin Anda hapus - dan baris baru, Anda mungkin melihat masalah.
rackandboneman
1

Jika itu satu-satunya direktori kosong (atau Anda tidak peduli menghapus direktori kosong lainnya), gunakanrmdir */ . Anda akan mendapatkan pesan kesalahan karena rmdirtidak dapat menghapus direktori yang tidak kosong, tetapi itu tidak masalah. rmdirDukungan GNU --ignore-fail-on-non-empty, atau Anda bisa 2>/dev/null.

Trailing /membuat glob hanya mencocokkan nama direktori.

Anda dapat memeriksa terlebih dahulu direktori kosong apa yang ada di bawah yang sedang digunakan
find -maxdepth 1 -type d -empty -ls. (Dan Anda dapat mengubah -lske -deletejika Anda mau).

Anda bisa menggunakan ekspresi glob yang lebih spesifik rmdir [^A-Za-z0-9._]/untuk mencocokkan direktori yang dimulai dengan nama file non-alfanumerik atau garis bawah. Saya juga termasuk ., tetapi ekspresi glob tidak cocok secara .normal.


Seperti yang telah ditunjukkan orang lain, Anda dapat membatasi itu untuk nama-karakter tunggal dengan gumpalan ?: rmdir ?/

rmdirtidak memiliki -ipilihan seperti rmitu, mungkin karena direktori kosong biasanya tidak bernilai dan hanya dapat dibuat ulang.

Peter Cordes
sumber
1
Anda ingin mengetahui direktori mana yang ingin Anda buat ulang, dan rmdirdapat memberi tahu Anda jika Anda memberikan -vopsi untuk itu (setidaknya di GNU).
Ruslan
@Ruslan: Tidak jika Anda memiliki direktori basi lain yang tidak Anda pedulikan lagi, dan menghapusnya akan menjadi bonus. Anda dapat mencari direktori kosong denganfind -maxdepth 1 -type d -empty -ls
Peter Cordes
-1

Sebelum melakukan sesuatu yang berisiko, coba ini dulu:

rmdir -- ^C

Secara umum - adalah pembatas yang memberitahu perintah no -o pion akan mengikuti, tetapi juga akan memungkinkan karakter aneh untuk tidak ditafsirkan sebagai sesuatu yang lain.

Contoh penggunaan lainnya adalah whois -r -- "-r OBJECT-RIPE"

(-r adalah jalan pintas untuk matang, tetapi dalam whois matang juga parameter)

Jika tidak berhasil pada percobaan pertama, maka mungkin mencoba rmdir -- "^C"

Tetapi pada csh shell saya, saya tidak membutuhkannya, hanya rmdir ^Csudah bekerja untuk saya.

Leo Vandew.
sumber
1
Dalam mengetik csh rmdir diikuti oleh <ctrl> C berfungsi? Benarkah?! Saya berharap itu berperilaku berbeda, yaitu membatalkan rmdirperintah dan mengembalikan Anda ke baris perintah.
Mausy5043
Memang akan. Lihat jawaban yang diterima tentang cara memasukkan karakter ^ C pada baris perintah.
Ale