#!/usr/bin/c++script // Present files ordered by size. // Even if the recurse option is used, the files are not presented by // directory, but a flat views shows all the files ordered by size #include string formatnum (size_t num, bool human) { if (num < 1000){ return format ("{}",num); }else if (human){ string_view suffix = ""; size_t fraction = 0; pair tblimit[]={ {1000*1000*1000*1000u,"T"},{1000*1000*1000u,"G"},{1000*1000u,"M"},{1000u,"K"} }; for (auto limit:tblimit){ if (num > limit.first){ fraction = (num % limit.first)/(limit.first/10.0)+0.5; num /= limit.first; if (fraction == 10){ fraction = 0; num++; } suffix = limit.second; break; } } return format ("{}.{}{}",num,fraction,suffix); }else{ // Insert , in long numbers. First turn num into string string tmp = format ("{}",num); string ret; // reverse tmp and seperate in chunks of 3 numbers. // put the range in it original order, but the content is itself reversed for (auto &&r:tmp|views::reverse|views::chunk(3)|views::reverse | views::transform([](auto &&s){return s|views::reverse;}) | views::join_with(","sv)){ ret += r; } return ret; } } #main progdesc("Search large files on disk"); option dirscan('d',"directory","Directory to scan",".",false); option human ('h',"human-readable","Present file size with suffix",false,false); option recurse('r',"recurse","Search sub-directory",false,false); option reverse('R',"reverse","Show largest files first",false,false); struct RESULT{ string dirname; string name; size_t size; }; vector results; vector dirs{dirscan.val}; while (dirs.size() > 0){ DIRNAME dir(dirs[0]); dirs.erase(dirs.begin()); for (auto &&st:dir.ls() | DIRNAME::drop_dot_dirs() | DIRNAME::stat()){ if (st.is_dir()){ //cout << format ("Dir {}/{}\n",st.dirname,st.name); if (recurse.val) dirs.push_back(format("{}/{}",st.dirname,st.name)); }else if (st.is_reg()){ //cout << format ("file {}/{}, mode {}, size {}\n",st.dirname,st.name,st.mode,st.size); results.emplace_back(st.dirname,st.name,st.size); } } } if (reverse.val){ ranges::sort(results,std::greater{},&RESULT::size); }else{ ranges::sort(results,std::less{},&RESULT::size); } for (auto &r:results) cout << format ("{:>15} {}/{}\n",formatnum(r.size,human.val),r.dirname,r.name);