code: public static File relativize(File target, File baseDir) {
          String separator = File.separator;
          try {
              String absTargetPath = target.getAbsolutePath();
              absTargetPath = FilenameUtils.normalizeNoEndSeparator(
                      FilenameUtils.separatorsToSystem(absTargetPath));
              String absBasePath = baseDir.getAbsolutePath();
              absBasePath = FilenameUtils.normalizeNoEndSeparator(
                      FilenameUtils.separatorsToSystem(absBasePath));
  
              if (filePathEquals(absTargetPath, absBasePath)) {
                  throw new IllegalArgumentException("target and base are equal: " + absTargetPath);
              }
  
              String[] absTargets = absTargetPath.split(Pattern.quote(separator));
              String[] absBases = absBasePath.split(Pattern.quote(separator));
  
              int minLength = Math.min(absTargets.length, absBases.length);
  
              int lastCommonRoot = -1;
              for (int i = 0; i < minLength; i++) {
                  if (filePathEquals(absTargets[i], absBases[i])) {
                      lastCommonRoot = i;
                  } else {
                      break;
                  }
              }
  
              if (lastCommonRoot == -1) {
                  // This case can happen on Windows when drive of two file paths differ.
                  throw new IllegalArgumentException("no common root");
              }
  
              String relativePath = "";
  
              for (int i = lastCommonRoot + 1; i < absBases.length; i++) {
                  relativePath = relativePath + ".." + separator;
              }
  
              for (int i = lastCommonRoot + 1; i < absTargets.length; i++) {
                  relativePath = relativePath + absTargets[i];
                  if (i != absTargets.length - 1) {
                      relativePath = relativePath + separator;
                  }
              }
              return new File(relativePath);
          } catch (Exception e) {
              throw new RuntimeException(String.format(
                      "target: %s; baseDir: %s; separator: %s", target, baseDir, separator), e);
          }
      }
docs: TODO ignore case for windows