Bagaimana cara menghapus direktori yang tidak dapat dihapus ini?

40

Saya membatalkan untar file tar yang korup, dan berhasil berakhir dengan beberapa direktori yang tidak dapat saya hapus, Jika saya mencoba menghapusnya, sepertinya tidak dapat ditemukan, tetapi lsmenunjukkannya ada, baik dengan bash dan dengan python saya dapatkan perilaku serupa, kecuali tepat setelah saya mencoba menghapusnya rm -rf, lsmengeluh tidak dapat menemukannya, lalu mencantumkannya (lihat di bawah setelah rm -rf). The findperintah menunjukkan file hadir, tapi masih saya tidak bisa memikirkan cara untuk menghapusnya.
Inilah usaha saya:

Di sini Anda melihat keduanya lsdan findsetuju kami memiliki direktori,

rl]$ ls
mikeaâ??cnt
rl]$ find -maxdepth 1 -type d -empty -print0  
./mikeaâcnt 

Tapi saya tidak bisa menghapusnya:

rl]$ find -maxdepth 1 -type d -empty -print0 |  xargs -0 rm -f -v 
rm: cannot remove `./mikeaâ\302\201\302\204cnt': Is a directory
rl]$ ls
mikeaâ??cnt

Saya bisa cdmelakukannya dan itu kosong:

rl]$ cd mikeaâ^Á^Äcnt/
mikeaâ^Á^Äcnt]$ ls
mikeaâ^Á^Äcnt]$ pwd
.../rl/mikeaâcnt


mikeaâ^Á^Äcnt]$ cd ../
rl]$ ls
mikeaâ??cnt

lihat di bawah ini bahwa ini bukan file sederhana tetapi direktori, dan lsberperilaku lucu setelah rm -rf dikatakan tidak dapat menemukan file kemudian daftar langsung setelah:

rl]$ rm mikeaâ^Á^Äcnt/
rm: cannot remove `mikeaâ\302\201\302\204cnt/': Is a directory
rl]$ rm -rf  mikeaâ^Á^Äcnt/
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt
rl]$ 

Jadi ini adalah percobaan dengan python, file ditemukan, tetapi namanya tidak dapat digunakan sebagai nama yang dapat dihapus:

rl]$ python 
Python 2.6.6 (r266:84292, Jul 10 2013, 22:48:45) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-3)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> import shutil
>>> os.listdir('.')
['mikea\xc3\xa2\xc2\x81\xc2\x84cnt']
>>> shutil.rmtree(os.listdir('.')[0] )
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.6/shutil.py", line 204, in rmtree
    onerror(os.listdir, path, sys.exc_info())
  File "/usr/lib64/python2.6/shutil.py", line 202, in rmtree
    names = os.listdir(path)
OSError: [Errno 2] No such file or directory: 'mikea\xc3\xa2\xc2\x81\xc2\x84cnt'

bahkan ketika saya menggunakan penyelesaian tab nama yang diambil tidak dapat digunakan:

rl]$ rm -rf mikeaâ^Á^Äcnt 
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt

menggunakan nama yang ditampilkan python dengan bash saya mendapatkan ini:

rl]$ rm -rf "mikea\xc3\xa2\xc2\x81\xc2\x84cnt"
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt

Apakah ada yang bisa saya lakukan untuk menghilangkan dir yang korup ini? Filesystem yang mendasari (NFS) tampaknya fungsional dan tidak ada masalah lain yang dilaporkan, dan saya tidak punya masalah sampai file tar rusak.

EDIT: Berikut ini menggunakan opsi findsendiri -execuntuk meneleponrm

rl]$ find -maxdepth 1 -type d -empty -exec rm -f {} \;
find: `./mikeaâ\302\201\302\204cnt': No such file or directory
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt
rl]$

tetapi file tersebut masih ada, ( lsmengeluh tidak dapat menemukannya, tetapi kemudian menunjukkannya)

EDIT ke-2:

rl]$ find -maxdepth 1 -type d -empty -exec rm -rf {} \;
find: `./mikeaâ\302\201\302\204cnt': No such file or directory
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt

Perilaku masih tidak berubah, file masih ada

EDIT ke-3:

rl]$ ls
mikeaâ??cnt
rl]$ find -maxdepth 1 -type d -empty -exec rm -rf {} + 
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt

Tampaknya ada lebih banyak nama daripada mikeaâcntmelihat output dari upaya python mikea\xc3\xa2\xc2\x81\xc2\x84cnt, dan tangkapan layar ini:

ls output

Edisi ke-4: Ini adalah upaya dengan kartu liar:

rl]$ echo * 
mikeaâcnt
rl]$ echo mike* 
mikeaâcnt
rl]$ rm -rf mike*
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt

dan lokal saya:

rl]$  locale
LANG=en_US.utf8
LC_CTYPE="en_US.utf8"
LC_NUMERIC="en_US.utf8"
LC_TIME="en_US.utf8"
LC_COLLATE="en_US.utf8"
LC_MONETARY="en_US.utf8"
LC_MESSAGES="en_US.utf8"
LC_PAPER="en_US.utf8"
LC_NAME="en_US.utf8"
LC_ADDRESS="en_US.utf8"
LC_TELEPHONE="en_US.utf8"
LC_MEASUREMENT="en_US.utf8"
LC_IDENTIFICATION="en_US.utf8"
LC_ALL=

Edit ke-5:

rl]$ ls -i 
ls: cannot access mikeaâcnt: No such file or directory
? mikeaâ??cnt

tetapi juga perilaku telah berubah, sekarang lsdan cd lakukan ini:

rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt
rl]$ cd mikeaâ^Á^Äcnt 
mikeaâcnt: No such file or directory.

Ini telah terjadi setelah upaya untuk menghapus, saya berpikir bahwa itu mungkin masalah NFS seperti yang disarankan dalam salah satu jawaban di sini oleh vinc17.

EDIT 6: Ini adalah output dari lsofdanls -a

rl] $ / usr / sbin / lsof mikeaâ ^ Á ^ Äcnt lsof: kesalahan status pada mikea \ xc2 \ x81 \ xc2 \ x84cnt: Tidak ada file atau direktori seperti itu

di atas salah, di sini adalah lsofdoa yang benar : (rl adalah direktori induk)

rl]$ /usr/sbin/lsof | grep mike | grep rl 
tcsh      11926   mike  cwd       DIR   0,33     4096 19569249 /home/mike/mish/rl
lsof      14733   mike  cwd       DIR   0,33     4096 19569249 /home/mike/mish/rl
grep      14734   mike  cwd       DIR   0,33     4096 19569249 /home/mike/mish/rl
grep      14735   mike  cwd       DIR   0,33     4096 19569249 /home/mike/mish/rl
lsof      14736   mike  cwd       DIR   0,33     4096 19569249 /home/mike/mish/rl
rl]$ 

rl]$ ls -a
ls: cannot access mikeaâcnt: No such file or directory
.  ..  mikeaâ??cnt

Sunting ke-7: pindah tidak akan berfungsi, (saya sudah mencoba sebelum semua ini, tapi saya tidak menyimpan output), tetapi memiliki masalah yang sama seperti lsdan rm dengan file.

8 EDIT: ini menggunakan karakter hex seperti yang disarankan:

 rl]$ ls --show-control-chars | xxd
0000000: 6d69 6b65 61c3 a2c2 81c2 8463 6e74 0a    mikea......cnt.
rl]$ rmdir $'mikea\6d69\6b65\61c3\a2c2\81c2\8463\6e74\0acnt' 
rmdir: failed to remove `mikea\006d69\006b651c3\a2c2\\81c2\\8463\006e74': No such file or directory
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt
rl]$

Edit ke-9: untuk statperintah:

 rl]$ stat  mikeaâ^Á^Äcnt 
stat: cannot stat `mikeaâ\302\201\302\204cnt': No such file or directory
 rl]$

Tampaknya bahkan lebih mungkin dari semua output, ada bug atau perilaku NFS lainnya seperti yang disarankan dalam komentar.

Sunting 10: Ini adalah strace output di intinya karena begitu besar, ini adalah output atau dua perintah ini:

strace -xx rmdir ./* | grep -e '-1 E'`
strace -xx -e trace=file ls -li`

https://gist.github.com/mikeatm/e07fa600747a4285e460

Sunting 11: Jadi sebelum di atas rmdirsaya perhatikan bahwa saya bisa cdmasuk ke direktori, tetapi setelah itu rmdirsaya tidak bisa cdlagi, mirip dengan kemarin. The .dan .. file yang hadir:

rl]$ ls
mikeaâ??cnt
rl]$ cd mikeaâ^Á^Äcnt/
mikeaâ^Á^Äcnt]$ ls
mikeaâ^Á^Äcnt]$ ls  -a
.  ..
mikeaâ^Á^Äcnt]$ cd ../

Edit Terakhir: Saya melihat admin lokal dan ini ditangani dengan masuk ke server itu sendiri dan menghapus dari sana. Penjelasan dari mereka adalah bahwa itu bisa menjadi masalah dengan set karakter di nama yang tidak pantas.

mike-m
sumber
Apakah ada alasan Anda mem-piping findoutput ke perintah yang berbeda alih-alih hanya menggunakan execopsi itu?
HalosGhost
@HalosGhost tidak ada alasan, lihat sunting untuk informasi tambahan tentang pertanyaan Anda
mike-m
2
Sebagai seseorang dengan sedikit pengalaman dengan unix dan linux, inilah ide saya: coba ganti nama direktori menjadi sesuatu tanpa menggunakan simbol-simbol tersebut mv. mungkin Anda bisa menghapusnya setelah itu. Atau, Anda dapat mencoba memindahkan direktori ke tingkat folder yang lebih dalam (mungkin dengan wildcard) dan kemudian menghapus folder tempat Anda memindahkannya.
Nzall
4
Saya menduga direktori hanya ada di memori pada klien dan sudah lama hilang di server. Sudahkah Anda mencoba umounting dan memasangnya lagi? Sudahkah Anda mencoba me-reboot klien? Apakah terlihat di klien lain?
kasperd
6
@ mike-m Sepertinya Anda telah menemukan bug NFS, mungkin di server NFS. Entah itu atau kerusakan sistem file di server. Saya ragu Anda benar-benar dapat melakukan hal lain selain menunggu admin server NFS menanganinya.
derobert

Jawaban:

11

Kutipan berikut dari esai ini berpotensi menjelaskan mengapa direktori itu menolak untuk dihapus:

NFSv4 mengharuskan semua nama file dipertukarkan menggunakan UTF-8 melalui kabel. Spesifikasi NFSv4, RFC 3530, mengatakan bahwa nama file harus dikodekan UTF-8 di bagian 1.4.3: “Dalam sedikit keberangkatan, nama file dan direktori dikodekan dengan UTF-8 untuk berurusan dengan dasar-dasar internasionalisasi.” Teks yang sama juga ditemukan di bagian NFS 4.1 RFC (RFC 5661) yang lebih baru 1.7.3. Klien Linux NFS saat ini hanya meneruskan nama file melalui tanpa konversi dari lokal saat ini ke dan dari UTF-8. Menggunakan nama file non-UTF-8 bisa menjadi masalah nyata pada sistem yang menggunakan sistem NFSv4 jarak jauh; setiap server NFS yang mengikuti spesifikasi NFS seharusnya menolak nama file non-UTF-8. Jadi jika Anda ingin memastikan bahwa file Anda benar-benar dapat disimpan dari klien Linux ke server NFS, saat ini Anda harus menggunakan nama file UTF-8. Dengan kata lain,

UTF-8 adalah pendekatan jangka panjang. Sistem harus mendukung UTF-8 dan juga banyak penyandian sebelumnya, memberi orang waktu untuk beralih ke UTF-8. Untuk menggunakan "UTF-8 di mana-mana", semua alat harus diperbarui untuk mendukung UTF-8. Bertahun-tahun yang lalu, ini adalah masalah besar, tetapi pada 2011 ini pada dasarnya adalah masalah yang diselesaikan, dan saya pikir lintasannya sangat jelas untuk beberapa sistem trailing tersebut.

Tidak semua urutan byte legal UTF-8, dan Anda tidak ingin harus mencari cara untuk menampilkannya. Jika kernel memberlakukan batasan-batasan ini, memastikan bahwa hanya nama file UTF-8 yang diizinkan, maka tidak ada masalah ... semua nama file akan sah UTF-8. Fungsi utf8_check C Markus Kuhn dapat dengan cepat menentukan apakah urutannya valid UTF-8.

Sistem file harus mensyaratkan bahwa nama file memenuhi beberapa standar, bukan karena beberapa kebutuhan jahat untuk mengendalikan orang, tetapi hanya agar nama dapat selalu ditampilkan dengan benar di lain waktu. Kurangnya standar membuat segalanya lebih sulit bagi pengguna, bukan lebih mudah. Namun sistem file tidak memaksa nama file menjadi UTF-8, sehingga dapat dengan mudah memiliki sampah.

Timothy Martin
sumber
Hal ini tampaknya menggemakan penjelasan dari admin lokal, saya akan menandai ini sebagai jawaban dari penjelasan admin. Lihat hasil edit terakhir saya
mike-m
19

Salah satu cara untuk menghapus file / direktori seperti ini adalah dengan inode-reference.

Untuk menemukan inode untuk elemen dalam dir saat ini:

ls -i
14813568 mikeaâcnt

Untuk menghapus ini:

find . -inum 14813568 -delete
Nicolai
sumber
silakan lihat suntingan ke-5.
mike-m
4
Tidak, ini tidak menghapus file dengan inode mereka. Ini mencari nama file untuk inode yang diberikan, dan kemudian menghapus file dengan namanya. Tidak dapat membantu di sini, karena upaya sudah dilakukan dengan nama yang benar (di samping upaya lain dengan nama yang salah).
Gilles 'SO- stop being evil'
@Gilles - secara teknis, mencari inode dentry dan mengembalikan nama file, tapi saya setuju.
mikeserv
1
@Nicolai tidak membantu saya. Direktori bukan pesan kosong muncul.
difraksi
1
Ya, hah, cerita lucu tentang ini: File yang saya coba hapus memiliki ?sebagai referensi inode-nya. Bagaimana Anda menghapusnya?
Nic Hartley
7

Anda tidak boleh menggunakan karakter non-ASCII di baris perintah karena seperti yang Anda lihat, untuk beberapa alasan, mereka tidak harus sesuai dengan nama file (Unicode memiliki berbagai cara untuk mengekspresikan huruf beraksen). Sesuatu seperti:

rm -rf mike*

harus bekerja karena nama file langsung dihasilkan oleh shell. Tetapi pastikan hanya ada satu kecocokan (lakukan yang echo mike*pertama untuk mengonfirmasi).

Nah, jika cdberhasil, maka tidak ada alasan mengapa rmatau lsharus mengatakan No such file or directory, sehingga masalahnya mungkin pada tingkat sistem file.

Catatan: Jangan gunakan lsuntuk menemukan apakah direktori kosong, tetapi ls -a.

Direktori masih dapat digunakan oleh proses lain (termasuk jika itu adalah cwd dari beberapa proses). IMHO, itu sebabnya masih "ada" tetapi dapat menghasilkan kesalahan, misalnya dengan ls; lsofmungkin memberi Anda beberapa informasi, tetapi dengan NFS, Anda perlu menemukan mesin mana yang menggunakannya. Terutama dengan NFS, ini dapat menghasilkan kesalahan aneh. ls -adalam direktori induk dapat menunjukkan .nfs*file / direktori kepada Anda dalam beberapa kasus.

Ketika Anda mendapatkan:

$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt

Saya menduga bahwa file masih ada di tabel direktori karena caching NFS dan / atau karena digunakan oleh proses lain, tetapi tanpa informasi terkait. Ketika lsmencoba untuk mendapatkan informasi tentang file itu sendiri, itu mendapat kesalahan karena file itu sendiri tidak ada lagi (hanya ada di tabel direktori), maka kesalahan yang ditampilkan. Kemudian lsmenampilkan nama file karena ada di tabel direktori. Fakta Anda memiliki tanda tanya dalam satu kasus tetapi tidak dalam kasus lain adalah karena bug tampilan lsIMHO (tidak terkait dengan masalah Anda).

vinc17
sumber
saya telah mencoba wildcard sebelumnya, tidak berhasil, dan saya gagal memposting upaya itu dalam pertanyaan saya, saya akan memperbarui dengan hasilnya
mike-m
Lihat hasil edit ketiga saya. IMHO ini karena NFS (mungkin bukan korupsi, tapi caching buruk) dan mungkin fakta bahwa proses lain menggunakan direktori. Dalam beberapa kasus, seseorang perlu me-reboot semuanya (server dan klien).
vinc17
Mungkin ini bisa menjelaskan banyak hal, tetapi saya tidak bisa memastikan karena saya tidak memiliki hak istimewa untuk mencatatnya. Lihat hasil edit ke-5.
mike-m
1
@ vinc17 Tolong jangan gunakan "EDIT" dalam jawaban Anda, karena untuk pembaca baru tidak masuk akal (sudah ada riwayat edit)
Bernhard
iv menambahkan beberapa output lsof, tidak yakin apakah itu dapat memberi tahu Anda apa pun,
mike-m
3

Saya secara pribadi telah diuji dengan menggunakan find's -execdirektif:

$ mkdir -p mikeaâcnt
$ ls
mikeaâcnt
$ find -maxdepth 1 -type d -empty -exec rm -rf {} +
$ ls
$ 

Folder itu dibuat dengan benar dan dihapus dengan benar.

Seperti yang ditunjukkan oleh @Igeorget , ada metode yang bahkan lebih sederhana jika Anda memiliki GNU find:

$ find -maxdepth 1 -type d -empty -delete

Saya juga menguji perintah ini, dan berfungsi dengan benar

HalosGhost
sumber
Dan jika Anda menggunakan find GNU, ada -deleteopsi juga.
Sayang
Silakan lihat hasil edit ke-3,
mike-m
1

Saya memiliki masalah yang sama, saya percaya. Saya telah melihat masalah sebelumnya dengan nama file . lsdalam hal ini ditampilkan file sebagai â??, tetapi saya dapat menghapusnya dengan rm ☃.

Ini mengarahkan saya ke cara berikut untuk mengonversi nama yang salah ke yang benar:

Pertama, dapatkan byte dari nama file:

$ ls --show-control-chars | xxd
0000000: 6d69 6b65 61c3 a2c2 81c2 8463 6e74 0a    mikea......cnt.

Kemudian decode byte ini sebagai UTF-8, untuk mendapatkan titik kode unicode, menggunakan input heksadesimal dari situs web ini misalnya: http://software.hixie.ch/utilities/cgi/unicode-decoder/utf8-decoder

U+006D LATIN SMALL LETTER M character
U+0069 LATIN SMALL LETTER I character
U+006B LATIN SMALL LETTER K character
U+0065 LATIN SMALL LETTER E character
U+0061 LATIN SMALL LETTER A character
U+00E2 LATIN SMALL LETTER A WITH CIRCUMFLEX character (&#x00E2;)
U+0081 <control> character (&#x0081;)
U+0084 <control> character (&#x0084;)
U+0063 LATIN SMALL LETTER C character
U+006E LATIN SMALL LETTER N character
U+0074 LATIN SMALL LETTER T character

Perhatikan ini semua di bawah batas byte. Kami memperoleh byte berikut:

6D 69 6B 65 61 E2 81 84 63 6E 74

Jika kami memperlakukan urutan ini di UTF-8 kami mendapatkan:

U+006D LATIN SMALL LETTER M character
U+0069 LATIN SMALL LETTER I character
U+006B LATIN SMALL LETTER K character
U+0065 LATIN SMALL LETTER E character
U+0061 LATIN SMALL LETTER A character
U+2044 FRACTION SLASH character (&#x2044;)
U+0063 LATIN SMALL LETTER C character
U+006E LATIN SMALL LETTER N character
U+0074 LATIN SMALL LETTER T character

Dan dengan demikian nama file Anda adalah:, mikea⁄cntdengan potongan kecil alih-alih yang normal. Anda sekarang dapat meneruskan nama ini ke rmdir.

DVD
sumber
Itu cerdik, jika saya bertemu ini lagi, saya ingat ini. bagus +1
mike-m
0

Setelah mendapatkan kode hex yang benar dari nama file / folder (menggunakan metode apa pun yang dianggap cocok, saya dapat memilih ls --show-control-chars | xxd), beberapa konstruk khusus harus digunakan untuk mengatasi karakter tersebut ketika berjalan di bawah bash:

rmdir $'mikea\xc3\xa2\xc2\x81\xc2\x84cnt'

Kalau tidak, backslash diperlakukan sebagai backslash vanila.

Abel Cheung
sumber
Silakan lihat edit saya (edit ke-8)
mike-m
@ mike-m Tentu saja itu tidak ada, karena lstermasuk baris baru dalam data output dan "cnt" digandakan. Mungkin Anda dapat mencoba langsung menyalin dan menempelkan baris dalam jawaban saya dan melihat apakah itu efektif?
Abel Cheung
Tidak, masih ini: `` `rl] $ rmdir $ 'mikea \ xc3 \ xa2 \ xc2 \ x81 \ xc2 \ x84cnt' rmdir: gagal menghapus` mikeaâ \ 302 \ 201 \ 302 \ 204cnt ': Tidak ada file atau direktori seperti itu `` `
mike-m
Dalam hal ini sangat mungkin kombinasi masalah NFS dan lokal mencegah sebagian besar utilitas sistem untuk melewatkan byte non-UTF8 yang salah. Dan sepertinya penghapusan inode memperburuk situasinya. Untuk saat ini, satu-satunya cara yang dapat saya pikirkan adalah mengatur sistem Anda ke lingkungan bebas-lokal (gunakan lokal "C" untuk LC_*dan LANGvariabel env), dan pasang NFS tanpa opsi set karakter apa pun
Abel Cheung
0

Sudahkah Anda mencoba menggunakan rm -rf ./mikeaâcntatau rm -rf "./mikeaâcnt"atau jalur absolut? Juga alih-alih rm, coba rmdir ./mikeaâcnt.

walsht
sumber
bagian dari masalahnya adalah bahwa karakter di mikeaâcnttampaknya bukan nama file, tetapi apa yang ls ditampilkan, lihat suntingan ke-3
mike-m
0

Sudahkah Anda mencoba mendapatkan inode dari file itu dengan stat:

stat mike*

Itu akan memberi Anda nomor inode (dan data lainnya), dan kemudian Anda bisa mencoba menghapusnya.

rsuarez
sumber
iv menambahkan hasil edit dengan statbehavour,
mike-m
0

Saya memiliki masalah serupa. Apakah Anda memiliki Gnome, KDE atau semacam Xwindow DM ?. Jika Anda membuka file broser dan menghapus file dari sana.

Itu harus bekerja.

Saya ingin melihat solusi dari baris perintah, tetapi dalam kasus saya dan setelah kehilangan banyak waktu mencoba mencari cara untuk menghapusnya dari baris perintah saya menemukan bahwa itu sesederhana menghapus file lain dari nautilus atau file explorer lainnya (kebenarannya saya hanya mencoba dengan nautilus).

YoMismo
sumber