首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 批量檔案重命名工具:鏈式規則引擎實戰與實測可用

     編輯:Java 相關知識

專案背景

下載影片/音樂常遇到檔名包含冗長廣告前後綴 (如「【某網站】電影名(廣告尾巴).mp4」),手動改名極其繁瑣。本工具支援多規則鏈式替換,一次處理整個資料夾。

核心設計:規則鏈模式

/** 重命名規則鏈:支援鏈式呼叫 addRule() */
public class RenameRuleChain {
    private final Map rules = new LinkedHashMap<>();  // 保持規則順序
    
    public RenameRuleChain addRule(String from, String to) {
        rules.put(from, to);
        return this;  // 鏈式呼叫
    }
    
    public Map getRules() {
        return Collections.unmodifiableMap(rules);
    }
}

重命名執行引擎

public class BatchRenamer {
    /** 批量重命名主入口 */
    public static void rename(String folderPath, RenameRuleChain ruleChain) {
        File folder = new File(folderPath);
        
        // 1. 參數驗證
        if (!folder.exists()) {
            throw new IllegalArgumentException("資料夾不存在: " + folderPath);
        }
        if (!folder.isDirectory()) {
            throw new IllegalArgumentException("路徑非資料夾: " + folderPath);
        }
        
        // 2. 取得檔案列表
        File[] files = folder.listFiles(File::isFile);  // 僅處理檔案,忽略子目錄
        if (files == null || files.length == 0) {
            System.out.println("資料夾無檔案: " + folderPath);
            return;
        }
        
        // 3. 套用規則逐一重命名
        int success = 0, failed = 0;
        for (File file : files) {
            String oldName = file.getName();
            String newName = applyRules(oldName, ruleChain.getRules());
            
            if (!oldName.equals(newName)) {
                File target = new File(folder, newName);
                if (target.exists()) {
                    System.err.printf("衝突跳過: %s → %s (目標已存在)%n", oldName, newName);
                    failed++;
                    continue;
                }
                
                if (file.renameTo(target)) {
                    System.out.printf("重命名: %s → %s%n", oldName, newName);
                    success++;
                } else {
                    System.err.printf("重命名失敗: %s → %s%n", oldName, newName);
                    failed++;
                }
            }
        }
        
        System.out.printf("完成! 成功: %d, 失敗: %d, 無變更: %d%n", 
            success, failed, files.length - success - failed);
    }
    
    /** 依序套用所有替換規則 */
    private static String applyRules(String fileName, Map rules) {
        String result = fileName;
        for (Map.Entry rule : rules.entrySet()) {
            result = result.replace(rule.getKey(), rule.getValue());
        }
        return result;
    }
}

使用範例

public class Main {
    public static void main(String[] args) {
        // 1. 建立規則鏈
        RenameRuleChain chain = new RenameRuleChain()
            .addRule("【我是一個好長好長的前綴哦】~~~~~", "")  // 移除前綴
            .addRule("(我是萌萌的小尾巴)", "")                // 移除後綴
            .addRule(" ", "_")                                   // 空格替換底線
            .addRule("(", "[").addRule(")", "]");                // 括號統一
        
        // 2. 執行重命名
        String targetFolder = "F:\\測試資料夾";  // 雙反斜線或正斜線均可
        BatchRenamer.rename(targetFolder, chain);
    }
}

執行前後對比

重命名前檔名列表

重命名後檔名列表

// 重命名前
【我是一個好長好長的前綴哦】~~~~~ 小說001(我是萌萌的小尾巴).txt
【我是一個好長好長的前綴哦】~~~~~ 小說002(我是萌萌的小尾巴).txt
【我是一個好長好長的前綴哦】~~~~~ 小說003(我是萌萌的小尾巴).txt

// 重命名後
小說001.txt
小說002.txt
小說003.txt

進階功能擴充

正則表達式支援

public class RegexRuleChain {
    private final List> rules = new ArrayList<>();
    
    public RegexRuleChain addRegex(String regex, String replacement) {
        rules.add(new Pair<>(Pattern.compile(regex), replacement));
        return this;
    }
    
    public String apply(String input) {
        String result = input;
        for (Pair rule : rules) {
            result = rule.getKey().matcher(result).replaceAll(rule.getValue());
        }
        return result;
    }
}
// 使用: .addRegex("\\[.*?\\]", "").addRegex("\\(.*?\\)", "")  // 移除所有 [] 和 () 內容

預覽模式 (Dry Run)

public void previewRename(String folderPath, RenameRuleChain chain) {
    File[] files = new File(folderPath).listFiles(File::isFile);
    System.out.println("=== 預覽模式 (不會實際重命名) ===");
    for (File f : files) {
        String newName = applyRules(f.getName(), chain.getRules());
        if (!f.getName().equals(newName)) {
            System.out.printf("%s  →  %s%n", f.getName(), newName);
        }
    }
}

撤銷功能 (Undo)

public class UndoableRenamer {
    private final List history = new ArrayList<>();
    
    public void renameWithUndo(String folder, RenameRuleChain chain) {
        File dir = new File(folder);
        File[] files = dir.listFiles(File::isFile);
        
        for (File f : files) {
            String oldName = f.getName();
            String newName = applyRules(oldName, chain.getRules());
            if (!oldName.equals(newName)) {
                File target = new File(dir, newName);
                if (f.renameTo(target)) {
                    history.add(new RenameRecord(target, new File(dir, oldName)));
                }
            }
        }
    }
    
    public void undo() {
        Collections.reverse(history);
        for (RenameRecord r : history) {
            r.getCurrent().renameTo(r.getOriginal());
        }
        history.clear();
    }
    
    static class RenameRecord {
        private final File current, original;
        RenameRecord(File current, File original) { this.current = current; this.original = original; }
        File getCurrent() { return current; }
        File getOriginal() { return original; }
    }
}

注意事項與最佳實踐

⚠️ 重要提醒

  • 不可逆操作:建議先執行預覽模式確認結果
  • 檔名衝突:規則導致多檔同名時會跳過,需手動處理
  • 編碼問題:中文檔名在不同 OS/檔案系統間可能亂碼,建議統一 UTF-8
  • 權限問題:唯讀檔案、系統檔案、被佔用檔案無法重命名
  • 遞迴處理:當前版本僅處理頂層檔案,子資料夾需遞迴呼叫

單元測試範例

@Test
public void testRuleChain() {
    RenameRuleChain chain = new RenameRuleChain()
        .addRule("prefix_", "")
        .addRule("_suffix", "")
        .addRule(" ", "-");
    
    assertEquals("file-name.txt", chain.applyRules("prefix_file name.txt_suffix"));
    assertEquals("no-change.txt", chain.applyRules("no-change.txt"));
}

@Test
public void testBatchRename() throws IOException {
    Path tempDir = Files.createTempDirectory("rename-test");
    Files.createFile(tempDir.resolve("old_001.txt"));
    Files.createFile(tempDir.resolve("old_002.txt"));
    
    BatchRenamer.rename(tempDir.toString(), 
        new RenameRuleChain().addRule("old_", "new_"));
    
    assertTrue(Files.exists(tempDir.resolve("new_001.txt")));
    assertTrue(Files.exists(tempDir.resolve("new_002.txt")));
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved