private static int doCopyDir(File originalDir, File copyDir, FileFilter filter,
			TaskMonitor monitor) throws IOException, CancelledException {
		if (!originalDir.exists()) {
			return 0;// nothing to do
		}

		File[] originalDirFiles = originalDir.listFiles(filter);
		if (originalDirFiles == null || originalDirFiles.length == 0) {
			return 0;// nothing to do
		}

		int copiedFilesCount = 0;
		for (File file : originalDirFiles) {
			monitor.checkCancelled();
			monitor.setMessage("Copying " + file.getAbsolutePath());
			File destinationFile = new File(copyDir, file.getName());
			if (file.isDirectory()) {
				copiedFilesCount += doCopyDir(file, destinationFile, filter, monitor);
			}
			else {
				destinationFile.getParentFile().mkdirs();

				// use a dummy monitor as not to ruin the progress
				copyFile(file, destinationFile, false, monitor);
				copiedFilesCount++;
			}
		}

		return copiedFilesCount;
	}
A version of {@link #copyDir(File, File, FileFilter, TaskMonitor)} that does not alter
the progress value of the given monitor, only the status text.  This allows this recursive
method to send status updates while the caller of this method controls the progress.
Ghidra/Framework/Utility/src/main/java/utilities/util/FileUtilities.java