argument('disk')); $disks = ($inputDisk === 'ALL') ? ['DISK01', 'DISK02', 'DISK03', 'DISK04', 'DISK05', 'DISK09', 'DISK10'] : [$inputDisk]; foreach ($disks as $diskName) { $this->info("========== 🔍 處理 {$diskName} =========="); $folder = $diskName; $prefix = $diskName; $this->processDisk($folder, $prefix); $this->newLine(); } $this->info('🎉 所有比對完成!'); return self::SUCCESS; } protected function processDisk(string $folder, string $prefix): void { $disk = Storage::disk('ftp_test'); $this->info("📂 FTP 目錄: {$folder}"); $this->info("🎯 DB prefix: {$prefix}"); // 1) 取得 FTP 檔案清單 $this->info('🔍 取得 FTP 檔案列表…'); $ftpPaths = collect($disk->allFiles($folder)) ->map(fn ($p) => strtolower(str_replace('\\', '/', ltrim($p, '/')))) ->filter(fn ($p) => Str::startsWith($p, strtolower($prefix))) ->unique() ->values(); $this->info("✅ FTP 檔案數:{$ftpPaths->count()}"); // 2) 資料庫 songs.filename $this->info('🗃️ 讀取資料庫 songs.filename…'); $dbPaths = Song::query() ->when($prefix, fn ($q) => $q->where('filename', 'like', $prefix . '%')) ->pluck('filename') ->map(fn ($p) => strtolower(str_replace('\\', '/', $p))) ->unique() ->values(); $this->info("✅ DB 記錄數:{$dbPaths->count()}"); // 3) 比對 $missing = $dbPaths->diff($ftpPaths); $extra = $ftpPaths->diff($dbPaths); // 4) 結果 $this->warn("❌ 缺失檔案(DB 有 / FTP 無):{$missing->count()}"); $missing->each(fn ($p) => $this->line(" - $p")); $this->info("⚠️ 多餘檔案(FTP 有 / DB 無):{$extra->count()}"); $extra->take(20)->each(fn ($p) => $this->line(" - $p")); if ($extra->count() > 20) $this->line(' …其餘省略'); } }