發布部署時常需篩選「上次發布後修改過的文件」。本文提供一個 Swing GUI 工具,掃描目錄、按修改時間篩選、生成 DOS 批次複製腳本,避免 Java 複製導致文件時間戳變更。
lastModified() > 基準時間 的文件xcopy /D /E /Y 批次腳本,保留目錄結構與時間戳public class IncrementalFileScanner {
public static List<File> scanModifiedAfter(File root, long baselineMillis) {
List<File> result = new ArrayList<>();
scanRecursive(root, baselineMillis, result);
return result;
}
private static void scanRecursive(File dir, long baseline, List<File> collector) {
File[] children = dir.listFiles();
if (children == null) return;
for (File child : children) {
if (child.isFile()) {
if (child.lastModified() > baseline) {
collector.add(child);
}
} else if (child.isDirectory()) {
scanRecursive(child, baseline, collector);
}
}
}
}
public class BatchScriptGenerator {
public static String generateXcopyScript(List<File> files, File sourceRoot, File targetRoot) {
StringBuilder sb = new StringBuilder();
sb.append("@echo off\n");
sb.append("rem 增量發布腳本 - 自動生成\n");
sb.append("rem 生成時間: ").append(new Date()).append("\n\n");
for (File file : files) {
String relativePath = getRelativePath(sourceRoot, file);
File targetFile = new File(targetRoot, relativePath);
String targetDir = targetFile.getParentFile().getAbsolutePath();
// 確保目標目錄存在
sb.append("if not exist \"").append(targetDir).append("\" mkdir \"").append(targetDir).append("\"\n");
// xcopy 保留屬性、時間戳、遞歸
sb.append("xcopy /D /E /Y /I \"").append(file.getAbsolutePath()).append("\" \"").append(targetDir).append("\\\"\n");
}
return sb.toString();
}
}
public class IncrementalDeployTool extends JFrame {
private JTextField sourceDirField, targetDirField;
private JSpinner baselineSpinner; // 日期時間選擇器
private JTextArea previewArea;
public IncrementalDeployTool() {
setTitle("增量發布文件篩選工具");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new BorderLayout());
// 配置面板
JPanel configPanel = new JPanel(new GridLayout(0, 2, 5, 5));
configPanel.add(new JLabel("源目錄:"));
sourceDirField = new JTextField(30);
configPanel.add(sourceDirField);
// ... 目標目錄、基準時間類似
JButton scanBtn = new JButton("掃描並預覽");
scanBtn.addActionListener(e -> doScan());
configPanel.add(scanBtn);
JButton genBtn = new JButton("生成部署腳本");
genBtn.addActionListener(e -> generateScript());
configPanel.add(genBtn);
add(configPanel, BorderLayout.NORTH);
previewArea = new JTextArea(20, 80);
previewArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
add(new JScrollPane(previewArea), BorderLayout.CENTER);
pack();
setLocationRelativeTo(null);
}
private void doScan() {
File source = new File(sourceDirField.getText());
File target = new File(targetDirField.getText());
long baseline = ((Date) baselineSpinner.getValue()).getTime();
List<File> modified = IncrementalFileScanner.scanModifiedAfter(source, baseline);
String script = BatchScriptGenerator.generateXcopyScript(modified, source, target);
previewArea.setText("找到 " + modified.size() + " 個修改文件\n\n" + script);
}
private void generateScript() {
// 寫入 deploy_incremental.bat
}
}
| 方式 | 時間戳保留 | 權限保留 | 效能 | 跨平台 |
|---|---|---|---|---|
Java NIO Files.copy() | 需額外 FileTime 設置 | 需額外處理 | 良好 | ✅ |
| Apache Commons IO | 支援 | 部分支援 | 良好 | ✅ |
xcopy /D /E /Y (Windows) | 原生保留 | 原生保留 | 極快 | ❌ |
rsync -av (Linux) | 原生保留 | 原生保留 | 極快 | ✅ |
生產環境建議使用成熟工具鏈:
maven-antrun-plugin / copy taskrsync/scpsynchronize 模組此工具適用於「無 CI/CD、手工部署、Windows 伺服器、需保留時間戳」的輕量級場景。核心邏輯可提取為獨立庫,整合至自動化流程中。