@argh_named("cp")
    @arg_verbose
    @arg_full_match
    @arg_host_access_method
    @arg_flag("-d", "--create-dest-dir", help="create missing remote target directories")
    @arg_flag("-r", "--recursive", help="copy directories recursively")
    @argh.arg('source', type=str, nargs="+", help='source file/dir to copy')
    @arg_target_nodes
    @argh.arg('dest_dir', type=str, help='destination remote directory')
    @expects_obj
    def handle_remote_cp(self, arg):
        """copy file(s) to remote node(s)"""
        def pp(pth):
            """pretty-print paths to output-safe ascii"""
            return repr(str(pth))[1:-1]

        # sanity check
        for source in arg.source:
            try:
                st = os.stat(source)
                if not arg.recursive and stat.S_ISDIR(st.st_mode):
                    raise errors.UserError("copy source {0} is a directory and no -r specified".format(
                            pp(source)))

            except __HOLE__ as err:
                raise errors.UserError("invalid copy source {0}: {1.__class__.__name__}: {1}".format(  # pylint: disable=E1306
                        pp(source), err))

        def copy_file_or_dir(node, remote, source_path, dest_dir):
            try:
                remote.stat(dest_dir)
            except errors.RemoteError as err:
                if not "Errno 2" in str(err):
                    raise errors.UserError("{0}: unexpected error checking target directory {1}: {2.__class__.__name__}: {2}".format(  # pylint: disable=E1306
                            node.name, pp(dest_dir), err))
                elif not arg.create_dest_dir:
                    raise errors.UserError("{0}: Remote directory {1} does not exist. (use -d to create it)".format(
                            node.name, pp(dest_dir)))

                remote.makedirs(dest_dir)

            if os.path.isdir(source_path):
                source_paths = [os.path.join(source_path, name) for name in os.listdir(source_path)]
            else:
                source_paths = [source_path]
            for file_path in source_paths:
                dest_path = os.path.join(dest_dir, os.path.basename(file_path))
                lstat = os.lstat(file_path.stat)
                if stat.S_ISDIR(lstat.st_mode):
                    copy_file_or_dir(node, remote, os.path.join(source_path, os.path.basename(file_path)), dest_path)
                    continue

                if arg.verbose:
                    self.log.info("copying: %s -> %s:%s [%s]", pp(file_path), node.addr(), pp(dest_dir), node.name)
                remote.put_file(file_path, dest_path)
                remote.utime(dest_path, (int(lstat.st_mtime),
                                         int(lstat.st_mtime)))

        def copy_op(arg, node, remote):
            for source in arg.source:
                copy_file_or_dir(node, remote, source, arg.dest_dir)

        copy_op.doc = "cp"
        confman = self.get_confman(arg.root_dir, reset_cache=False)
        self.remote_op(confman, arg, copy_op)
dataset/ETHPy150Open ohmu/poni/poni/tool.py/Tool.handle_remote_cp