public static void mvFileToFinalPath(Path specPath, String unionSuffix, Configuration hconf,
                                       boolean success, Logger log, DynamicPartitionCtx dpCtx, FileSinkDesc conf,
                                       Reporter reporter) throws IOException,
      HiveException {

    // There are following two paths this could could take based on the value of shouldAvoidRename
    //  shouldAvoidRename indicate if tmpPath should be renamed/moved or now.
    //    if false:
    //      Skip renaming/moving the tmpPath
    //      Deduplicate and keep a list of files
    //      Pass on the list of files to conf (to be used later by fetch operator)
    //    if true:
    //       1) Rename tmpPath to a new directory name to prevent additional files
    //          from being added by runaway processes.
    //       2) Remove duplicates from the temp directory
    //       3) Rename/move the temp directory to specPath

    FileSystem fs = specPath.getFileSystem(hconf);
    Path tmpPath = Utilities.toTempPath(specPath);
    Path taskTmpPath = Utilities.toTaskTempPath(specPath);
    if (!StringUtils.isEmpty(unionSuffix)) {
      specPath = specPath.getParent();
    }
    PerfLogger perfLogger = SessionState.getPerfLogger();
    boolean isBlobStorage = BlobStorageUtils.isBlobStorageFileSystem(hconf, fs);
    boolean avoidRename = false;
    boolean shouldAvoidRename = shouldAvoidRename(conf, hconf);

    if(isBlobStorage && (shouldAvoidRename|| ((conf != null) && conf.isCTASorCM()))
        || (!isBlobStorage && shouldAvoidRename)) {
      avoidRename = true;
    }
    if (success) {
      if (!avoidRename && fs.exists(tmpPath)) {
        //   1) Rename tmpPath to a new directory name to prevent additional files
        //      from being added by runaway processes.
        // this is only done for all statements except SELECT, CTAS and Create MV
        Path tmpPathOriginal = tmpPath;
        tmpPath = new Path(tmpPath.getParent(), tmpPath.getName() + ".moved");
        LOG.debug("shouldAvoidRename is false therefore moving/renaming " + tmpPathOriginal + " to " + tmpPath);
        perfLogger.perfLogBegin("FileSinkOperator", "rename");
        Utilities.rename(fs, tmpPathOriginal, tmpPath);
        perfLogger.perfLogEnd("FileSinkOperator", "rename");
      }

      // Remove duplicates from tmpPath
      List<FileStatus> statusList = HiveStatsUtils.getFileStatusRecurse(
          tmpPath, ((dpCtx == null) ? 1 : dpCtx.getNumDPCols()), fs);
      FileStatus[] statuses = statusList.toArray(new FileStatus[statusList.size()]);
      if(statuses != null && statuses.length > 0) {
        Set<FileStatus> filesKept = new HashSet<>();
        perfLogger.perfLogBegin("FileSinkOperator", "RemoveTempOrDuplicateFiles");
        // remove any tmp file or double-committed output files
        int dpLevels = dpCtx == null ? 0 : dpCtx.getNumDPCols(),
            numBuckets = (conf != null && conf.getTable() != null) ? conf.getTable().getNumBuckets() : 0;
        List<Path> emptyBuckets = removeTempOrDuplicateFiles(
            fs, statuses, unionSuffix, dpLevels, numBuckets, hconf, null, 0, false, filesKept, false);
        perfLogger.perfLogEnd("FileSinkOperator", "RemoveTempOrDuplicateFiles");
        // create empty buckets if necessary
        if (!emptyBuckets.isEmpty()) {
          perfLogger.perfLogBegin("FileSinkOperator", "CreateEmptyBuckets");
          createEmptyBuckets(
              hconf, emptyBuckets, conf.getCompressed(), conf.getTableInfo(), reporter);
          for(Path p:emptyBuckets) {
            FileStatus[] items = fs.listStatus(p);
            filesKept.addAll(Arrays.asList(items));
          }
          perfLogger.perfLogEnd("FileSinkOperator", "CreateEmptyBuckets");
        }

        // move to the file destination
        Utilities.FILE_OP_LOGGER.trace("Moving tmp dir: {} to: {}", tmpPath, specPath);
        if(shouldAvoidRename(conf, hconf)){
          // for SELECT statements
          LOG.debug("Skipping rename/move files. Files to be kept are: " + filesKept.toString());
          conf.getFilesToFetch().addAll(filesKept);
        } else if (conf !=null && conf.isCTASorCM() && isBlobStorage) {
          // for CTAS or Create MV statements
          perfLogger.perfLogBegin("FileSinkOperator", "moveSpecifiedFileStatus");
          LOG.debug("CTAS/Create MV: Files being renamed:  " + filesKept.toString());
          if (conf.getTable() != null && conf.getTable().getTableType().equals(TableType.EXTERNAL_TABLE)) {
            // Do this optimisation only for External tables.
            createFileList(filesKept, tmpPath, specPath, fs);
          } else {
            Set<String> filesKeptPaths = filesKept.stream().map(x -> x.getPath().toString()).collect(Collectors.toSet());
            moveSpecifiedFilesInParallel(hconf, fs, tmpPath, specPath, filesKeptPaths);
          }
          perfLogger.perfLogEnd("FileSinkOperator", "moveSpecifiedFileStatus");
        } else {
          // for rest of the statement e.g. INSERT, LOAD etc
          perfLogger.perfLogBegin("FileSinkOperator", "RenameOrMoveFiles");
          LOG.debug("Final renaming/moving. Source: " + tmpPath + " .Destination: " + specPath);
          renameOrMoveFilesInParallel(hconf, fs, tmpPath, specPath);
          perfLogger.perfLogEnd("FileSinkOperator", "RenameOrMoveFiles");
        }
      }
    } else {
      Utilities.FILE_OP_LOGGER.trace("deleting tmpPath {}", tmpPath);
      fs.delete(tmpPath, true);
    }
    Utilities.FILE_OP_LOGGER.trace("deleting taskTmpPath {}", taskTmpPath);
    fs.delete(taskTmpPath, true);
  }
returns null if path is not exist
ql/src/java/org/apache/hadoop/hive/ql/exec/Utilities.java