2012年4月25日水曜日

boost::filesystem 同一ファイルを削除

画像処理をしていて、空白だけの画像を削除したいと思って作りました。 空白だけの画像ファイルを、どっかにコピーして、そのファイルと同じファイルならディレクトリーをトラバースして削除していきます。シェルスクリプトでも書けるんでしょうけど、C++偏執狂には、こっちの方が処理コストが安い。
#include <boost/filesystem.hpp>
#include <boost/scoped_array.hpp>
#include <fstream>
#include <iomanip>
#include <iostream>
namespace fs = boost::filesystem;

void traverse_directory( const fs::path& p, int fsiz, const char* buf );

void traverse_directory( const fs::path& p, int fsiz, const char* buf ) {
  fs::directory_iterator de;
  fs::directory_iterator ds( p );
  for( fs::directory_iterator p = ds; p != de; ++p ) {
    if( fs::is_directory( *p ) ) {
      std::cout << "D:" << *p << std::endl;
      traverse_directory( (*p).path(), fsiz, buf );
    } else {
      int nsiz = fs::file_size( (*p).path() );
      if( nsiz == fsiz ) {
        boost::scoped_array<char> buf2( new char [nsiz] );
        {
          std::ifstream ifs( (*p).path().generic_string().c_str(), std::ios::in | std::ios::binary );
          ifs.read( buf2.get(), nsiz );
        }
        if( 0 == memcmp( buf, buf2.get(), nsiz ) ) {
          std::cout << "same delete : " << *p << std::endl;
          fs::remove( *p );
        }
      //} else {
        //std::cout << *p << std::endl;
      }
    }
  }
}

void show_usage() {
  std::cout << " ファイルをバイナリで比較して、同じものを削除します" << std::endl;
  std::cout << "nulldel [root folder] [compare file]" << std::endl;
}

int main(int argc, char* argv[] ) {
  if( argc != 3 ) {
    show_usage();
    return 1;
  }
  int fsiz = fs::file_size( argv[2] );
  boost::scoped_array<char> buf( new char [ fsiz ] );
  {
    std::ifstream ifs( argv[2], std::ios::in | std::ios::binary );
    ifs.read( buf.get(), fsiz );
  }
  traverse_directory( argv[1], fsiz, buf.get() );
  return 0;
}

0 件のコメント: