text: #coding=utf-8
  '''
  Created on 2016年9月27日
  Tool  functions for file system operation and I/O. 
  In the style of linux shell commands
  '''
  import os
  import pickle as pkl
  import subprocess
  import logging
  from . import strs, io
  
  
  def mkdir(path):
      """
      If the target directory does not exists, it and its parent directories will created. 
      """
      path = get_absolute_path(path)
      if not exists(path):
          os.makedirs(path)
      return path
  
  def make_parent_dir(path):
      """make the parent directories for a file."""
      parent_dir = get_dir(path)
      mkdir(parent_dir)
      
      
  def pwd():
      return os.getcwd()
  
  def dump(path, obj):
      path = get_absolute_path(path)
      parent_path = get_dir(path)
      mkdir(parent_path)
      with open(path, 'w') as f:
          logging.info('dumping file:' + path);
          pkl.dump(obj, f)
  
  def load(path):
      path = get_absolute_path(path)
      with open(path, 'r') as f:
          data = pkl.load(f)
      return data
  
  def join_path(a, *p):
      return os.path.join(a, *p)
  
  def is_dir(path):
      path = get_absolute_path(path)
      return os.path.isdir(path)
  
  is_directory = is_dir
  
  def is_path(path):
      path = get_absolute_path(path)
      return os.path.ispath(path)
      
  def get_dir(path):
      '''
      return the directory it belongs to.
      if path is a directory itself, itself will be return 
      '''
      path = get_absolute_path(path)
      if is_dir(path):
          return path;
      return os.path.split(path)[0]
  
  def get_parent_dir(path):
      current_dir = get_dir(path)
      return get_absolute_path(join_path(current_dir, '..'))
  
  def get_filename(path):
      return os.path.split(path)[1]
  
  def get_absolute_path(p):
      if p.startswith('~'):
          p = os.path.expanduser(p)
      return os.path.abspath(p)
  
  def cd(p):
      p = get_absolute_path(p)
      os.chdir(p)
      
  def ls(path = '.', suffix = None):
      """
      list files in a directory.
      return file names in a list
      """
      path = get_absolute_path(path)
      files = os.listdir(path)
  
      if suffix is None:       
          return files
          
      filtered = []
      for f in files:
          if string.ends_with(f, suffix, ignore_case = True):
              filtered.append(f)
      
      return filtered
  
  def find_files(pattern):
      import glob
      return glob.glob(pattern)
  
  def read_lines(p):
      """return the text in a file in lines as a list """
      p = get_absolute_path(p)
      f = open(p,'rU')
      return f.readlines()
      
  def write_lines(p, lines, append_break = False):
      p = get_absolute_path(p)
      make_parent_dir(p)
      with open(p, 'w') as f:
          for line in lines:
              if append_break:
                  f.write(line + '\n')
              else:
                  f.write(line)
  
  def cat(p):
      """return the text in a file as a whole"""
      cmd = 'cat ' + p
      return subprocess.getoutput(cmd)
  
  def exists(path):
      path = get_absolute_path(path)
      return os.path.exists(path)
  
  def not_exists(path):
      return not exists(path)
  
  def load_mat(path):
      import scipy.io as sio
      path = get_absolute_path(path)
      return sio.loadmat(path)
  
  def dump_mat(path, dict_obj, append = True):
      import scipy.io as sio
      path = get_absolute_path(path)
      make_parent_dir(path)
      sio.savemat(file_name = path, mdict =  dict_obj, appendmat = append)
      
  def dir_mat(path):
      '''
      list the variables in mat file.
      return a list: [(name, shape, dtype), ...]
      '''
      import scipy.io as sio
      path = get_absolute_path(path)
      return sio.whosmat(path)
      
  SIZE_UNIT_K = 1024
  SIZE_UNIT_M = SIZE_UNIT_K ** 2
  SIZE_UNIT_G = SIZE_UNIT_K ** 3
  def get_file_size(path, unit = SIZE_UNIT_K):
      size = os.path.getsize(get_absolute_path(path))
      return size * 1.0 / unit
      
      
  def create_h5(path):
      import h5py
      path = get_absolute_path(path)
      make_parent_dir(path)
      return h5py.File(path, 'w');
  
  def open_h5(path, mode = 'r'):
      import h5py
      path = get_absolute_path(path)
      return h5py.File(path, mode);
      
  def read_h5(h5, key):
      return h5[key][:]
  def read_h5_attrs(h5, key, attrs):
      return h5[key].attrs[attrs]
      
  def copy(src, dest):
      io.make_parent_dir(dest)
      import shutil
      shutil.copy(get_absolute_path(src), get_absolute_path(dest))
      
  cp = copy
  
  def remove(p):
      import os
      os.remove(get_absolute_path(p))
  rm = remove
  
  def search(pattern, path, file_only = True):
      """
      Search files whose name matches the give pattern. The search scope
      is the directory and sub-directories of 'path'. 
      """
      path = get_absolute_path(path)
      pattern_here = io.join_path(path, pattern)
      targets = []
      
      # find matchings in current directory
      candidates = find_files(pattern_here)
      for can in candidates:
          if io.is_dir(can) and file_only:
              continue
          else:
              targets.append(can)
              
      # find matching in sub-dirs
      files = ls(path)
      for f in files:
          fpath = io.join_path(path, f)
          if is_dir(fpath):
              targets_in_sub_dir = search(pattern, fpath, file_only)
              targets.extend(targets_in_sub_dir)
      return targets
  
  def dump_json(path, data):
      import ujson as json
      path = get_absolute_path(path)
      make_parent_dir(path)
  
      with open(path, 'w') as f:
          json.dump(data, f)
      return path
  
  def load_json(path):
      import ujson as json
      path = get_absolute_path(path)
      with open(path, 'r')  as f:
          return json.load(f)
  