Satu berkas cukup dilakukan manual; lima ratus berkas menuntut otomasi. Kondisi khasnya: satu folder berisi hasil pengukuran per hari (data_001.csv sampai data_500.csv), sebagian besar sehat, beberapa terpotong saat transfer, dan kita tidak tahu yang mana. Chapter ini merakit pola pemrosesan banyak berkas: mengumpulkan nama berkas lewat dir dengan wildcard, menggabungkan path dengan fullfile, memproses tiap berkas di dalam try-catch agar satu berkas rusak tidak menghentikan seluruh pekerjaan, lalu merangkum hasil lintas berkas. Cakupan kita:
- pola
dir('*.csv')dan wildcard umum lainnya - path aman lintas sistem operasi dengan
fullfile try-catchper berkas: gagal satu, lanjut sisanya, catat yang gagal- agregasi hasil dari struct array menjadi ringkasan satu layar
Mengumpulkan Berkas dengan dir dan Wildcard #
Aturannya: jangan pernah mengetik nama berkas satu per satu — biarkan dir yang mendaftar. Mekanisme di balik layar: dir mengembalikan struct array dengan satu elemen per berkas; tiap elemen memuat field name, folder, bytes, dan isdir, terurut sesuai sistem operasi. Wildcard yang didukung dir sama dengan pola file umum:
| Pola | Arti | Contoh kecocokan |
|---|---|---|
data_*.csv | mulai data_, akhir .csv | data_001.csv, data_2024.csv |
*.csv | semua berkas CSV | transaksi.csv, sensor.csv |
sensor?.txt | satu karakter bebas | sensor1.txt, sensorA.txt |
* | semua berkas dan folder | termasuk subfolder (field isdir) |
Menghitung jumlah berkas hasil seleksi adalah verifikasi termurah sebelum memproses — bila folder itu seharusnya berisi 500 berkas namun dir hanya menemukan 499, ada satu berkas hilang nama atau salah ekstensi:
daftar = dir('data_*.csv');
fprintf('ditemukan %d berkas dengan pola data_*.csv\n', numel(daftar));
assert(numel(daftar) == 4, 'jumlah berkas tidak sesuai');Output yang Dihasilkan:
ditemukan 4 berkas dengan pola data_*.csvPath Aman dengan fullfile #
Aturan kedua: gabungkan folder dan nama berkas dengan fullfile, bukan dengan [folder '\' nama]. Mekanismenya: fullfile menempel pemisah yang benar untuk sistem operasi berjalan — / di Linux dan macOS, \ di Windows — sehingga kode portabel di komputer mana pun. Field folder dari hasil dir bahkan bisa kosong bila kita memanggil dir dari folder kerja itu sendiri; fullfile tetap aman karena fungsi tersebut mengabaikan komponen kosong:
berkas = fullfile(daftar(k).folder, daftar(k).name);Satu baris tersebut menghasilkan path lengkap yang valid di kedua sistem operasi — dan menjadi input bagi fungsi bacaRingkas yang membaca satu berkas.
Try-Catch per Berkas #
Aturan inti pemrosesan massal: satu berkas korup tidak boleh meruntuhkan 499 berkas lain. Mekanisme di balik layar: bagian rentan dibungkus try; bila bacaRingkas melempar error — misalnya berkas terpotong sehingga tidak punya baris data — eksekusi melompat ke blok catch, loop berlanjut ke iterasi berikutnya, dan kegagalan tercatat di struct array hasil:
hasil = struct('status', {}, 'n', {}, 'rata', {}, 'maks', {});
fprintf('\nproses sungguhan:\n');
for k = 1:numel(daftar)
berkas = fullfile(daftar(k).folder, daftar(k).name);
try
r = bacaRingkas(berkas);
hasil(k).status = true;
hasil(k).n = r.n;
hasil(k).rata = r.rata;
hasil(k).maks = r.maks;
fprintf('SUKSES: %-13s n=%d rata=%7.2f maks=%g\n', ...
daftar(k).name, r.n, r.rata, r.maks);
catch
hasil(k).status = false;
hasil(k).n = 0;
hasil(k).rata = NaN;
hasil(k).maks = NaN;
fprintf('GAGAL : %-13s tidak terbaca — dilewati\n', daftar(k).name);
end
endMari kita bedah baris-baris kode di atas:
- Baris 1 (
hasil = struct('status', {}, ...)): struct array kosong dengan empat field; penulisan{}di nilai membuat array0×0siap tumbuh. - Baris 5 (
berkas = fullfile(...)): tiap iterasi membangun path penuh dari elemendaftarke-k— tidak ada nama file yang dikodekan keras. - Baris 7 (
r = bacaRingkas(berkas)): fungsi pembaca (berkasbacaRingkas.m) melempar error untuk berkas tanpa baris data; error inilah yang ditangkapcatch. - Baris 8-12 (blok
try): hasil sukses disimpan dan dilaporkan;%-13smerata-kiri nama berkas agar kolom berbaris. - Baris 13-19 (blok
catch): kegagalan tidak menghentikan loop — statusfalseplus nilaiNaNmenandai elemen yang bermasalah, pesanGAGALtercetak, lalu iterasi berikutnya berjalan.
Berkas bacaRingkas.m sendiri sengaja ketat: assert(isequal(size(M, 2), 1)) menolak kolom tak terduga dan assert(numel(M) >= 1) menolak berkas kosong — galat yang jelas, bukan angka nol yang menyelinap masuk sebagai data sah.
Dry-Run Sebelum Menjalankan #
Pola dry-run berarti mencetak rencana sebelum mengeksekusinya. Mekanismenya: loop pertama hanya menampilkan nama berkas — tanpa membuka satu pun berkas — sehingga kita bisa memeriksa pola wildcard dan urutan pemrosesan tanpa risiko. Setelah yakin, loop kedua (proses sungguhan) melakukan pekerjaan berat:
fprintf('\nDRY-RUN — berkas yang akan diproses:\n');
for k = 1:numel(daftar)
fprintf(' %s\n', daftar(k).name);
endPada empat berkas uji, dry-run mencetak daftar lengkap; pada 500 berkas produksi, kita tinggal membatasi pencetakan atau menghitung pola nama sebelum memutuskan.
Agregasi Hasil Lintas Berkas #
Setelah loop selesai, hasil adalah struct array berisi n, rata, maks per berkas plus status. Merangkumnya memakai penggabungan [...] dan logical indexing:
statusVec = [hasil.status];
nSukses = sum(statusVec);
totalBaris = sum([hasil.n]);
rataGabung = mean([hasil(statusVec).rata]);
korup = {daftar(~statusVec).name};
fprintf('\nringkasan: %d/%d berkas sukses\n', nSukses, numel(daftar));
fprintf('total baris terbaca : %d\n', totalBaris);
fprintf('rata-rata gabungan : %.2f\n', rataGabung);
fprintf('berkas bermasalah : %s\n', korup{1});Output yang Dihasilkan (berkas contoh.m lengkap — membuat 4 berkas uji, memproses, lalu menghapus semuanya):
ditemukan 4 berkas dengan pola data_*.csv
DRY-RUN — berkas yang akan diproses:
data_001.csv
data_002.csv
data_003.csv
data_004.csv
proses sungguhan:
SUKSES: data_001.csv n=3 rata= 20.00 maks=30
SUKSES: data_002.csv n=4 rata= 20.00 maks=35
SUKSES: data_003.csv n=2 rata= 105.00 maks=110
GAGAL : data_004.csv tidak terbaca — dilewati
ringkasan: 3/4 berkas sukses
total baris terbaca : 9
rata-rata gabungan : 48.33
berkas bermasalah : data_004.csv
BERSIH: 4 berkas uji dihapus, contoh selesaiMari kita bedah baris-baris kunci agregasi:
- Baris 1 (
[hasil.status]): operator[...]pada struct array mengumpulkan satu field dari semua elemen menjadi vektor logis4×1— trik yang sama dengan[hasil.n]. - Baris 4 (
[hasil(statusVec).rata]): logical indexing pada struct memilih elemen sukses saja, lalu mengumpulkan fieldrata— rata-rata gabungan dihitung dari 3 berkas sehat, bukan dariNaNberkas gagal. - Baris 5 (
{daftar(~statusVec).name}): nama berkas bermasalah dikumpulkan ke cell array untuk dilaporkan.
Ringkasan #
Rantai lengkapnya: dir('data_*.csv') mendaftar berkas, fullfile menjahit path yang aman, try-catch per berkas menjaga satu korup tidak menular, dry-run memverifikasi rencana, dan [hasil.field] plus logical indexing merangkum semuanya. Skrip contoh.m membuktikan pola tersebut empat berkas uji (tiga sehat, satu terpotong): 3/4 sukses, 9 baris terbaca, berkas bermasalah teridentifikasi — dan folder bersih kembali setelah skrip selesai.