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-catch per 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:

PolaArtiContoh kecocokan
data_*.csvmulai data_, akhir .csvdata_001.csv, data_2024.csv
*.csvsemua berkas CSVtransaksi.csv, sensor.csv
sensor?.txtsatu karakter bebassensor1.txt, sensorA.txt
*semua berkas dan foldertermasuk 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:

matlab
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:

text
ditemukan 4 berkas dengan pola data_*.csv

Path 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:

matlab
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:

matlab
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
end

Mari kita bedah baris-baris kode di atas:

  1. Baris 1 (hasil = struct('status', {}, ...)): struct array kosong dengan empat field; penulisan {} di nilai membuat array 0×0 siap tumbuh.
  2. Baris 5 (berkas = fullfile(...)): tiap iterasi membangun path penuh dari elemen daftar ke-k — tidak ada nama file yang dikodekan keras.
  3. Baris 7 (r = bacaRingkas(berkas)): fungsi pembaca (berkas bacaRingkas.m) melempar error untuk berkas tanpa baris data; error inilah yang ditangkap catch.
  4. Baris 8-12 (blok try): hasil sukses disimpan dan dilaporkan; %-13s merata-kiri nama berkas agar kolom berbaris.
  5. Baris 13-19 (blok catch): kegagalan tidak menghentikan loop — status false plus nilai NaN menandai elemen yang bermasalah, pesan GAGAL tercetak, 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:

matlab
fprintf('\nDRY-RUN — berkas yang akan diproses:\n');
for k = 1:numel(daftar)
    fprintf('  %s\n', daftar(k).name);
end

Pada 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:

matlab
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):

text
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 selesai

Mari kita bedah baris-baris kunci agregasi:

  1. Baris 1 ([hasil.status]): operator [...] pada struct array mengumpulkan satu field dari semua elemen menjadi vektor logis 4×1 — trik yang sama dengan [hasil.n].
  2. Baris 4 ([hasil(statusVec).rata]): logical indexing pada struct memilih elemen sukses saja, lalu mengumpulkan field rata — rata-rata gabungan dihitung dari 3 berkas sehat, bukan dari NaN berkas gagal.
  3. 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.