Bagaimana Saya Menghemat Ratusan Gigabyte Disk di Ratusan Project Pemrograman
On this page
- Pendahuluan
- A. Apa sebenarnya yang memakan ruang itu
- B. Tiga hambatan yang menghalangi
- Metode
- A. Aturan sibling manifest
- B. Pengecualian Python
- C. Kenapa requirements.txt bukan opsional
- D. Menemukan kandidat tanpa masuk ke dalamnya
- E. Menghapus dengan konfirmasi
- F. Dua mode, karena satu saja tak pernah cukup
- Hasil dan Pembahasan
- A. Yang berhasil dikembalikan
- B. Kenapa satu direktori mendominasi
- C. Di luar filesystem
- Simpulan
- Istilah
Pekerjaan saya menulis software, yang sehari-harinya berarti mengetik file text berukuran kecil. Satu file source paling beberapa kilobyte. Seluruh code yang saya ketik sendiri untuk satu project barangkali dua puluh megabyte. Namun disk tetap saja penuh, berkali-kali, di mesin dengan SSD 512 GB bahkan satu terabyte. Bertahun-tahun saya menganggapnya janggal, dan sama lamanya saya menerimanya sebagai ongkos wajar dari profesi ini.
Keduanya keliru. Ruangnya habis bukan oleh tulisan saya, melainkan oleh apa yang dihasilkan tools di sebelah tulisan itu. Pada satu folder berisi lima project biasa, saya mengukur 21 GB, dan 19.84 GB di antaranya ternyata material yang bisa dibangun ulang kapan pun. Itu 94% dari totalnya, dan tak satu pun benar-benar karya saya. Tulisan ini memaparkan metode yang saya pakai untuk mengenali material tersebut secara presisi, melacaknya di seluruh mesin, lalu menghapusnya tanpa sekali pun mempertaruhkan pekerjaan sungguhan.
Pendahuluan
Peringatannya biasanya muncul di tengah pekerjaan lain. Installer berhenti, build gagal separuh jalan, editor menolak menyimpan, dan notifikasi memberi kabar bahwa tersisa beberapa gigabyte di drive yang setahun lalu masih lapang. Tak ada peristiwa besar di antaranya. Tak ada satu file pun yang membengkak sampai memenuhi disk. Ruangnya terkikis sedikit demi sedikit lewat rutinitas biasa, masing-masing tak kasat mata saat terjadi, dan totalnya baru ketahuan ketika disk sudah mentok.
Yang membuat persoalan ini layak ditulis: pertumbuhannya sebenarnya bukan berasal dari pekerjaannya. Keluaran seorang developer mungil, dan tetap mungil. Yang membesar justru tools di sekelilingnya — library yang diunduh project supaya bisa jalan, file antara yang ditinggalkan compiler, cache yang disimpan framework agar build berikutnya lebih cepat. Semua itu berguna selama project masih aktif. Masalahnya, tak ada yang membereskannya ketika project berhenti aktif, sehingga mesin berumur beberapa tahun memanggul sisa endapan dari setiap project yang pernah berjalan di atasnya.
Sebelum melangkah lebih jauh, perlu dijelaskan dulu sisa endapan itu wujudnya seperti apa, sebab seluruh metode ini bertumpu pada kemampuan membedakan satu jenis folder dari jenis lainnya.
A. Apa sebenarnya yang memakan ruang itu
Hampir tak ada program yang ditulis sepenuhnya dari nol. Setiap project mendeklarasikan library luar yang dibutuhkannya, lalu package manager — tools yang tugasnya mengambil dan memasang library tersebut — mengunduh semuanya ke satu folder di dalam project. Folder itulah yang disebut dependency folder. Di dunia JavaScript namanya node_modules; di PHP namanya vendor; di Python ia bersemayam di dalam virtualenv, direktori mandiri yang memuat salinan interpreter beserta seluruh library yang terpasang khusus untuk satu project itu.
Folder semacam ini besar karena alasan yang mudah luput. Satu project barangkali hanya menyebut sepuluh library, tapi tiap library menyebut library lain lagi, dan begitu seterusnya bertingkat-tingkat. Package manager memasang seluruh pohonnya. Sepuluh dependency langsung rutin mekar jadi ratusan package terpasang, lengkap dengan dokumentasi, test, dan definisi tipenya. Begitulah aplikasi kecil bisa berakhir dengan node_modules ratusan megabyte, dan itu pula sebabnya folder tersebut hampir selalu berlipat-lipat lebih besar ketimbang code yang benar-benar ditulis developernya.
Kategori kedua bernama build artifact: apa pun yang dihasilkan compiler atau bundler dalam perjalanan dari source code menuju program siap jalan. Bahasa terkompilasi memproduksi paling banyak, sebab yang disimpan bukan cuma binary jadinya, melainkan juga hasil antara untuk tiap file dan tiap dependency, supaya build berikutnya cukup mengulang bagian yang berubah saja. Rust menaruh semuanya di target, Flutter di build, dan tools web di dist atau .next. Inilah harga dari build yang cepat, dan harga itu dibayar dengan ruang disk yang tak pernah ditagih kembali siapa pun.
Bagian ketiga justru yang membuat dua bagian sebelumnya boleh dibuang. Manifest adalah file tempat project mencatat library apa saja yang dipakainya beserta versinya — package.json untuk Node.js, composer.json untuk PHP, Cargo.toml untuk Rust, pubspec.yaml untuk Flutter, requirements.txt untuk Python. Ukurannya beberapa kilobyte teks, disimpan di version control berdampingan dengan source, dan justru karena file inilah folder raksasa di sebelahnya boleh dibuang: satu perintah membaca manifest, lalu folder itu tersusun kembali. Source code dan manifest, itulah project-nya. Sisanya cuma cache yang kebetulan berumur panjang.
Ketimpangan inilah yang dimanfaatkan artikel ini. Beberapa kilobyte teks sanggup memproduksi ulang gigabyte demi gigabyte folder, yang berarti gigabyte-gigabyte itu tersimpan tanpa alasan lain selain tak ada yang pernah menghapusnya.
Jawaban paling gampang untuk disk yang penuh tentu membeli disk yang lebih besar, dan kadang memang itu langkah yang benar. Tapi harga storage sedang merangkak naik karena infrastruktur AI memperebutkan pasokan yang sama, sehingga mengganti drive bukan lagi refleks murah seperti dulu. Lagi pula ada alasan yang lebih kuat ketimbang harga. Membeli kapasitas demi menampung file yang bisa memulihkan dirinya sendiri sama saja membayar untuk menyimpan barang yang sejak awal tak perlu disimpan.
Skalanya yang bikin persoalan ini menarik. Mesin kerja bisa memuat puluhan project, masing-masing berisi beberapa module, sehingga folder kandidatnya berjumlah ratusan. Membersihkan sebanyak itu dengan tangan gagal karena tiga alasan terpisah, dan ketiganya saling menumpuk.
Tak mungkin semua lokasinya masih diingat. Project mengendap di direktori yang sudah bertahun-tahun tak terpikirkan lagi.
Kerjanya lambat, jadi biasanya ditinggalkan di tengah jalan, dan pembersihannya tak pernah benar-benar rampung.
Pengerjaannya dilakukan sambil dikejar waktu. Memilih cepat-cepat, secara manual, di antara ratusan folder yang tampak serupa — persis begitulah cara kerja sungguhan ikut terhapus tanpa sengaja.
Otomasi menjawab ketiganya sekaligus. Ia juga melipatgandakan akibat dari satu kekeliruan, karena script menerapkan definisi apa pun yang diberikan ke ratusan direktori dalam hitungan detik. Definisi yang ceroboh tidak menghasilkan pembersihan yang ceroboh; hasilnya penghapusan yang cepat, penuh percaya diri, dan tak bisa dibatalkan, atas barang yang keliru. Karena itulah metode berikut menumpahkan sebagian besar tenaganya pada definisi, bukan pada penghapusan.
B. Tiga hambatan yang menghalangi
Jadi tujuannya gampang dirumuskan: membebaskan ruang itu di seluruh project yang ada di mesin, berulang kali, tanpa membeli disk yang lebih besar dan tanpa sekali pun menghapus kode yang benar-benar saya tulis sendiri. Mengotomasinya adalah satu-satunya cara yang sanggup mengimbangi jumlahnya.
Gampang dirumuskan, canggung dibangun. Menulis script-nya cuma menghabiskan satu sore; yang jauh lebih lama adalah memutuskan apa yang boleh dihapusnya — dan justru bagian itulah yang layak dicatat. Ada tiga hambatan yang berdiri antara tujuan tadi dan script yang boleh dipercaya mengerjakannya, dan masing-masing menutup jalan keluar yang paling pertama terpikirkan.
Pertama, nama folder sama sekali tak membuktikan isinya. Cara yang paling gampang terpikir adalah menyiapkan daftar nama untuk dihapus — node_modules, vendor, target, build — dan cara itu keliru dengan model yang baru ketahuan sesudah rusak. Folder bernama vendor di satu project berisi dependency PHP, di project lain berisi data supplier. Folder bernama build di satu tempat adalah output Flutter, di tempat lain folder kerja seseorang. Mengurutkan berdasarkan ukuran pun gagal dengan alasan serupa: besar tak berarti boleh dibuang, dan folder terbesar di sebuah mesin bisa saja justru satu-satunya yang tak pernah di-backup. Aturan apa pun yang bersandar pada nama folder atau ukurannya cepat atau lambat akan menghapus pekerjaan sungguhan — dan karena ia script, penghapusan itu terjadi di ratusan direktori sebelum ada yang sempat sadar.
Kedua, Python tak mengikuti aturan yang memecahkan hambatan pertama. Hampir semua ekosistem lain meninggalkan manifest tepat di sebelah folder yang dihasilkannya, dan justru itulah yang membuat folder tersebut terbukti boleh dibuang. Virtualenv Python tidak begitu. Ia tak mewajibkan file apa pun di sebelahnya, dan namanya bebas — venv, .venv, env, atau apa saja yang terpikir saat project itu dibuat. Aturan paling aman dalam metode ini punya titik buta persis di salah satu ekosistem yang paling banyak dipakai, dan membiarkannya berarti merelakan gigabyte yang tak tersentuh.
Ketiga, skala dan keselamatan tarik-menarik. Meminta konfirmasi tiap folder satu per satu memang rancangan yang aman, tapi di mesin dengan ratusan kandidat rancangan itu pula yang menjamin pekerjaannya ditinggalkan di tengah jalan — disk tetap penuh, pekerjaan setengah selesai. Menghapus semuanya sekali jalan memang tuntas, tapi ia melenyapkan satu-satunya momen ketika manusia masih sempat menangkap kekeliruan. Keduanya punya alasan, dan tak satu pun memadai kalau berdiri sendiri.
Ketiganya dibahas di seksi tersendiri di bawah. Urutannya bukan kebetulan: yang pertama menentukan apa yang boleh dihapus, yang kedua menambal celah yang ditinggalkan aturan itu, dan yang ketiga menentukan bagaimana penghapusannya dijalankan.
Metode
Prosedurnya tiga tahap, dan urutannya tak bisa ditawar: tetapkan apa yang boleh dibuang, temukan dengan andal, lalu hapus dengan konfirmasi. Tiap tahap bergantung pada ketepatan tahap sebelumnya.
Definisi saya lebih sempit dari kesan pertamanya. Folder boleh dibuang jika dan hanya jika ia bisa dibangun ulang dari apa yang masih tersisa di disk. Bukan karena ukurannya besar, bukan karena namanya mirip cache, dan bukan pula karena saya tidak mengenalinya. Ukuran dan keasingan justru dua kriteria yang terasa paling meyakinkan saat itu juga, sekaligus paling berpeluang memusnahkan barang berharga.
Nama folder tak pernah membuktikan isinya. Buktinya ada pada manifest yang duduk di sebelahnya.
Dua contoh tandingan memperlihatkan kenapa pembedaan ini memikul seluruh jaminan keamanannya. Direktori bernama vendor bisa berupa dependency tree PHP, bisa juga arsip data pemasok milik bisnis. Direktori bernama build bisa berupa keluaran Flutter, bisa juga tempat seorang rekan menaruh hasil kerja untuk klien. Mencocokkan berdasarkan nama saja memusnahkan keduanya, dan memusnahkannya tanpa bersuara.
A. Aturan sibling manifest
Inilah jawaban atas hambatan pertama: membuktikan folder boleh dihapus tanpa memercayai namanya.
Pembeda kedua kasus tadi terletak pada ada tidaknya file manifest di sebelah folder tersebut: di parent directory yang sama, pada level yang sama, bukan di dalamnya. Selama manifest itu ada, isi folder tadi bisa dibangkitkan kembali darinya, dan justru itulah yang membuatnya boleh dibuang. Pasangan yang saya andalkan sebagai berikut.
node_modules- boleh dibuang bila ada
package.jsondi sebelahnya (Node.js) vendor- boleh dibuang bila ada
composer.jsondi sebelahnya (PHP, Laravel) target- boleh dibuang bila ada
Cargo.tomldi sebelahnya (Rust) build- boleh dibuang bila ada
pubspec.yamldi sebelahnya (Flutter, Dart) dist- keluaran build, boleh dibuang bila ada
package.jsonataupyproject.toml .next,.nuxt- cache framework, boleh dibuang bila ada
package.json .gradle- cache milik Gradle sendiri, tersusun ulang pada build berikutnya
Ditulis sebagai perintah, aturannya terbaca nyaris sama seperti dalam kalimat biasa. Pengujiannya cuma satu kondisi; selebihnya sekadar sambungan.
# Temukan folder vendor/ Laravel — tapi hanya yang punya sibling
# composer.json sebagai bukti folder itu bisa dibangun ulang.
| while ; do
if [; then
fi
Saya memilih $(dirname "$dir") ketimbang "$dir/.." karena bunyinya persis seperti "folder di sebelahnya", dan gagasan itulah yang menopang seluruh aturan ini.
B. Pengecualian Python
Inilah jawaban atas hambatan kedua: ekosistem tempat aturan di atas tak punya manifest untuk disandari.
Python melanggar aturan tadi, dan memahami alasannya jauh lebih baik daripada memberinya perlakuan khusus tanpa berpikir. Virtualenv tak punya manifest wajib di sebelahnya, dan namanya bebas — venv, .venv, env, atau nama khas project tertentu. Tak ada file tetangga yang bisa membuktikan bahwa direktori sebelah memang environment.
Maka pengujiannya bergeser dari manifest ke struktur direktorinya sendiri, yang cukup khas untuk dijadikan kesimpulan.
# Virtualenv tak punya manifest di sebelahnya, jadi deteksi strukturnya:
# pyvenv.cfg, atau bin/activate berdampingan dengan executable python.
Prinsipnya tetap sama. Saya masih menuntut bukti bahwa folder itu regenerable; buktinya saja yang kini dibaca dari isi direktorinya sendiri, bukan dari tetangganya.
C. Kenapa requirements.txt bukan opsional
Pengecualian ini datang bersama kewajiban, dan inilah bagian metode yang paling berfaedah bagi siapa pun yang menulis Python. Menghapus virtualenv baru aman kalau ia sungguh-sungguh regenerable, dan virtualenv baru regenerable kalau isinya pernah dicatat. Tak ada mekanisme yang mengurus pembukuan itu untuk kita.
Jadi jangan pernah memasang library lalu membiarkannya tak tercatat. Catat, supaya environment-nya bisa disusun ulang dari catatan, bukan dari ingatan.
# Bangun ulang environment dari catatan, bukan dari ingatan.
File requirements.txt, atau daftar dependency di dalam pyproject.toml bagi yang lebih menyukai tata letak modern, pada dasarnya mengerjakan secara manual apa yang dilakukan package.json dan Cargo.toml secara otomatis. Rawat terus kemutakhirannya, maka virtualenv jadi sama boleh dibuangnya dengan node_modules. Telantarkan, dan direktori itu sama sekali bukan sampah: ia satu-satunya catatan tersisa tentang apa yang dibutuhkan project supaya bisa berjalan.
D. Menemukan kandidat tanpa masuk ke dalamnya
Seksi-seksi berikutnya menjawab hambatan ketiga, dimulai dari cara menemukan kandidatnya lebih dulu.
Pencariannya harus berangkat dari titik mana pun yang ditunjuk lalu turun sampai dasar, sebab premis seluruh latihan ini memang lokasi semua project sudah tak diingat lagi. Ada satu detail yang bobotnya melebihi penampakannya. Begitu satu direktori cocok, scan wajib berhenti menuruninya.
Tanpa itu, penelusuran bakal mendaftar tiap file di dalam dependency tree yang toh sebentar lagi dihapus, lalu dengan riang melaporkan node_modules bersarang yang ditemukannya di sana — padahal semuanya lenyap bersama induknya. Di find, perintahnya -prune.
# -prune menghentikan penelusuran di tiap folder yang cocok: tak perlu masuk
# ke dependency tree yang sebentar lagi dihapus, dan tak ada duplikat bersarang.
Inilah pembeda antara scan yang rampung sambil ditunggu dan scan yang akhirnya ditinggalkan.
E. Menghapus dengan konfirmasi
Otomasi bertugas menemukan kandidatnya; keputusannya tetap di tangan saya. Tiap kandidat ditampilkan lengkap dengan path-nya, terdeteksi sebagai apa, dan — yang paling penting — ukurannya, sebelum apa pun menimpanya.
size=
# Baca dari /dev/tty, bukan stdin — daftar kandidat ada di stdin.
case "" in
y|yes) && ;;
q|quit) ; break ;;
*) ;;
esacDua pilihan di situ disengaja. Prompt-nya [y/N/q] dengan N kapital, jadi bawaannya tidak, dan tekanan Enter karena lengah cuma melewati folder itu tanpa memusnahkannya. Lalu jawabannya dibaca dari /dev/tty, bukan dari standard input, sebab standard input sudah dipakai mengangkut daftar kandidat. Kalau dibaca dari sana, prompt itu diam-diam menelan daftarnya dan tak pernah menunggu jawaban — bug yang hampir selalu ditemui orang saat pertama kali mem-pipe daftar file ke dalam loop.
F. Dua mode, karena satu saja tak pernah cukup
Inilah hambatan ketiga, sekaligus bagian yang membuat saya berubah pikiran sesudah script-nya dipakai. Konfirmasi per folder memang default yang benar, tapi ia tak cocok dengan pekerjaan yang sebenarnya. Di mesin dengan ratusan kandidat, menjawab pertanyaan yang sama dua ratus kali bukanlah kehati-hatian — begitulah caranya pembersihan berhenti di kandidat kesembilan puluh, dengan disk yang masih penuh.
Jalan keluar yang saya tolak adalah flag yang sekadar melewati semua pertanyaan. Cara itu mengubah tool yang hati-hati menjadi tool yang cepat, sekaligus melenyapkan satu-satunya titik ketika manusia masih bisa menyadari ada sesuatu di daftar itu yang semestinya tak ikut terhapus.
Yang dilakukan mode borongan justru memindahkan konfirmasinya, bukan meniadakannya. Ia mencetak seluruh daftar lebih dulu — tiap path, terdeteksi sebagai apa, dan berapa ukurannya — lalu total yang akan dibebaskan, baru bertanya tepat sekali.
Selisihnya lebih berarti daripada kelihatannya. Menjawab dua ratus pertanyaan bukan berarti mengambil dua ratus keputusan — sesudah yang kedua puluh, jawabannya jadi refleks, dan refleks itulah yang menghapus folder yang keliru. Satu pertanyaan yang diajukan atas daftar yang lengkap, disertai totalnya, adalah satu keputusan sungguhan yang diambil dengan informasi lebih banyak daripada yang dibawa tiap prompt satuan tadi.
Kedua mode berbagi satu sifat yang benar-benar menjalankan fungsi keselamatannya: ukuran dihitung dan ditampilkan sebelum ada yang dihapus, bukan sesudah. Folder yang tertulis 17 GB memancing orang menengok dua kali dengan cara yang tak pernah dilakukan sederet path polos, dan lebih dari sekali angka itulah yang membuat saya berhenti lalu memeriksa apa yang hendak saya buang.
Satu hal lagi pantas ditaruh di sini, sebab menghentikan penghapusan yang panjang itu lumrah dilakukan. Script memasang handler untuk Ctrl-C supaya berhenti di tengah jalan berakhir secara sengaja, bukan meninggalkan terminal dalam keadaan apa pun yang kebetulan ditemui interupsi itu.
# Berhenti di tengah jalan itu wajar, jadi buat penutupannya tertib.
Yang sudah terlanjur dihapus tentu tak kembali. Yang didapat dari sini adalah penutupan yang bersih dan ringkasan jujur tentang apa saja yang sempat terjadi sebelum interupsi, bukan proses setengah jalan yang tak melaporkan apa-apa.
Hasil dan Pembahasan
Metode ini baru sepadan dengan panjangnya penjelasan kalau menghasilkan angka, jadi bagian ini melaporkan apa yang sungguh dikembalikan oleh scan, lalu menelusuri makna dari sebaran angka tersebut.
A. Yang berhasil dikembalikan
Supaya metodenya terukur dan bukan cuma diklaim, saya menyiapkan satu folder berisi lima project dari ekosistem berbeda — Flutter, Laravel, Node.js, Python, dan Rust — masing-masing dalam kondisi sebagaimana lazimnya di mesin kerja, dengan dependency terpasang dan build sudah dijalankan. Pengukuran sebelum dan sesudah itulah yang mengubah klaim menjadi hasil.
Scan mengenali tujuh folder di lima project tadi. Ukurannya disalin persis seperti yang dilaporkan.
| Folder | Terdeteksi sebagai | Ukuran |
|---|---|---|
flutter_example/android/.gradle | Gradle cache | 13 MB |
flutter_example/build | Flutter / Dart | 2.7 GB |
laravel_example/vendor | PHP / Composer | 107 MB |
nodejs_example/dist | keluaran build | 1.8 MB |
nodejs_example/node_modules | Node.js | 222 MB |
python_example/venv-oauth2-tools | Python virtualenv | 37 MB |
rust_example/target | Rust / Cargo | 17.0 GB |
| Total dibebaskan | 19.84 GB |
Lima project, dan 94% ruangnya tak memuat satu baris pun tulisan saya. Lima direktori yang tersisa berisi source code, manifest, dan konfigurasinya — segala bekal untuk membangkitkan kembali seluruh 19.84 GB itu kapan pun diperlukan.
B. Kenapa satu direktori mendominasi
Sebarannya memberi pelajaran lebih banyak ketimbang totalnya. Satu direktori saja, target milik Rust, menyumbang 17 GB — sekitar 86% dari seluruh ruang yang dibebaskan. Artefak hasil kompilasi mendominasi karena di dalamnya tersimpan state incremental build dan debug symbol untuk tiap dependency dalam pohonnya, dan karena tak pernah ada yang mengingatkan supaya dibersihkan. Direktori build Flutter, dengan 2.7 GB, menyusul di urutan kedua dengan alasan serupa.
Ada konsekuensi praktisnya. Bagi yang bekerja dengan bahasa terkompilasi, rasio di mesin sendiri kemungkinan lebih tinggi daripada mesin yang didominasi project bahasa interpretatif, dan satu direktori target yang terlupakan bisa bernilai lebih besar daripada seluruh node_modules yang dimiliki kalau digabungkan. Ini juga menerangkan kenapa pendekatan manual begitu konsisten gagalnya: penyumbang terbesarnya justru direktori yang sekali pun belum pernah dibuka.
Rasionya, bukan angka mutlaknya, yang bisa dibawa ke mana-mana. Di mesin saya sendiri, dengan jumlah project menembus ratusan, sekali jalan sanggup mengembalikan ruang dalam hitungan ratusan gigabyte — tapi angka itu sepenuhnya bergantung pada seberapa banyak yang menumpuk dan dalam bahasa apa, jadi anggap saja itu pengalaman saya, bukan janji. Yang 94% itulah bagian yang bisa diverifikasi sendiri di disk masing-masing dalam beberapa menit dengan dua perintah di atas.
C. Di luar filesystem
Satu teknik di luar scan filesystem layak disebut, sebab prinsipnya sama dan hasilnya kerap setimpal. Docker image regenerable menurut definisinya sendiri, sebab ia di-build ulang atau di-pull ulang begitu dibutuhkan.
Perintah ini rutin membebaskan puluhan gigabyte. Catatannya, -a menyapu setiap image yang tidak dirujuk container yang sedang berjalan, sehingga pemakaian berikutnya mesti membayar ulang ongkos build atau download. Di koneksi cepat itu pertukaran yang adil; di bandwidth berkuota atau lambat, atau untuk image yang sulit di-pull ulang, lebih baik selektif.
Satu catatan soal pengukuran, karena angka-angka di atas bersandar padanya. Script melaporkan ukuran memakai du --apparent-size, yakni ukuran logis file. Pada filesystem terkompresi atau sparse, angkanya bisa berbeda dari block yang benar-benar dilepaskan. Angka itu tepat untuk memutuskan apakah folder itu layak dihapus, bukan untuk meramal persis berapa yang nanti dilaporkan disk.
Berikut rekaman yang menelusuri persoalan dan script yang sama, bagi yang lebih suka menyaksikan langsung proses pemindaian dan penghapusannya ketimbang membacanya.
Simpulan
Peringatan low disk space tak pernah datang di saat yang enak. Ia menyeruak di tengah pekerjaan, dan naluri pertamanya memburu file besar lalu menghapus apa pun yang terlihat asing — prosedur paling buruk yang bisa dibayangkan, karena keputusan tak terbalikkan diambil serba cepat, di bawah tekanan, tanpa keterangan apa pun tentang isi tiap file. Satu perintah yang menyodorkan kandidat regenerable lengkap dengan ukuran dan klasifikasinya, dan yang bawaannya tidak, mengubah momen itu dari risiko menjadi rutinitas. Justru itu, lebih daripada gigabyte-nya, yang membuat metode ini layak dirumuskan.
Saya mendemonstrasikannya di Ubuntu dengan implementasi bash, tapi bagian yang portabel memang metodenya, bukan code-nya: tetapkan regenerable secara presisi, buktikan lewat sibling manifest, scan tanpa menuruni yang sudah cocok, lalu konfirmasi dengan ukuran sebelum menghapus. Keempat gagasan itu bisa dibawa ke PowerShell, Python, atau apa pun yang lebih disukai. Porting ke Windows perlu satu penyesuaian, sebab virtualenv di sana memakai Scripts/activate, bukan bin/activate.
Manfaatnya berskala mengikuti seberapa banyak folder regenerable yang menumpuk, sehingga metode ini berharga di mesin pengembangan yang aktif dan nyaris tak berguna di laptop yang tak dipakai membangun software. Bagi yang memang membangun software, tahap definisi itulah bagian yang layak ditiru. Selebihnya cuma pekerjaan mekanis.
Istilah
- Regenerable
- Folder yang bisa dibangun ulang sepenuhnya dari file yang masih tersisa di disk setelah ia dihapus.
- Manifest
- File yang mendeklarasikan dependency project, dan yang darinya folder dependency bisa disusun ulang.
- Sibling
- File yang berada di parent directory yang sama dengan folder yang sedang diuji, pada level yang sama, bukan di dalamnya.
- Prune
- Menginstruksikan scan rekursif untuk berhenti menuruni direktori begitu ia cocok.
Technologies covered
- Bash
- Python
- Linux
- Docker