google-site-verification: google61fe8ba583a51912.html
Batch File Renamer in Java

Introduction

A comprehensive batch file renamer utility that provides multiple renaming strategies, preview capabilities, and robust error handling. This tool can handle various file renaming scenarios including pattern-based renaming, sequential numbering, case conversion, and more.

Core Implementation

Main Batch File Renamer Class

import java.io.*; import java.nio.file.*; import java.util.*; import java.util.regex.*; import java.util.stream.Collectors; public class BatchFileRenamer { private final List<File> files; private final List<RenameOperation> operations; private boolean previewMode; public BatchFileRenamer() { this.files = new ArrayList<>(); this.operations = new ArrayList<>(); this.previewMode = true; // Default to preview mode for safety } public void addFile(File file) { if (file.exists() && file.isFile()) { files.add(file); } else { throw new IllegalArgumentException("File does not exist or is not a regular file: " + file.getPath()); } } public void addFiles(List<File> files) { for (File file : files) { addFile(file); } } public void addFilesFromDirectory(File directory, boolean recursive) { if (!directory.exists() || !directory.isDirectory()) { throw new IllegalArgumentException("Directory does not exist: " + directory.getPath()); } try { List<File> foundFiles = findFiles(directory, recursive); files.addAll(foundFiles); } catch (IOException e) { throw new RuntimeException("Error reading directory: " + e.getMessage(), e); } } private List<File> findFiles(File directory, boolean recursive) throws IOException { if (!recursive) { return Arrays.stream(Objects.requireNonNull(directory.listFiles())) .filter(File::isFile) .collect(Collectors.toList()); } List<File> result = new ArrayList<>(); Files.walk(directory.toPath()) .filter(Files::isRegularFile) .forEach(path -> result.add(path.toFile())); return result; } public void setPreviewMode(boolean previewMode) { this.previewMode = previewMode; } // Renaming operations public void addReplaceOperation(String search, String replacement) { operations.add(new ReplaceOperation(search, replacement)); } public void addRegexOperation(String regex, String replacement) { operations.add(new RegexOperation(regex, replacement)); } public void addPrefixOperation(String prefix) { operations.add(new PrefixOperation(prefix)); } public void addSuffixOperation(String suffix) { operations.add(new SuffixOperation(suffix)); } public void addCaseOperation(CaseType caseType) { operations.add(new CaseOperation(caseType)); } public void addSequentialNumbering(String prefix, String suffix, int startNumber, int digits) { operations.add(new SequentialNumberingOperation(prefix, suffix, startNumber, digits)); } public void addExtensionChange(String newExtension) { operations.add(new ExtensionChangeOperation(newExtension)); } public void addCustomOperation(RenameOperation operation) { operations.add(operation); } public List<RenameResult> previewRename() { return performRename(true); } public List<RenameResult> executeRename() { return performRename(false); } private List<RenameResult> performRename(boolean preview) { List<RenameResult> results = new ArrayList<>(); Map<String, Integer> nameCounts = new HashMap<>(); for (File originalFile : files) { try { String originalName = originalFile.getName(); String newName = applyOperations(originalName); // Handle name conflicts newName = resolveNameConflict(originalFile.getParent(), newName, nameCounts); File newFile = new File(originalFile.getParent(), newName); RenameResult result = new RenameResult(originalFile, newFile, RenameStatus.PENDING); if (!preview) { boolean success = originalFile.renameTo(newFile); result = new RenameResult(originalFile, newFile, success ? RenameStatus.SUCCESS : RenameStatus.FAILED); if (success) { // Update the file reference for subsequent operations files.set(files.indexOf(originalFile), newFile); } } results.add(result); } catch (Exception e) { results.add(new RenameResult(originalFile, null, RenameStatus.ERROR, e.getMessage())); } } return results; } private String applyOperations(String filename) { String result = filename; for (RenameOperation operation : operations) { result = operation.apply(result); } return result; } private String resolveNameConflict(String directory, String filename, Map<String, Integer> nameCounts) { String baseName = filename; String extension = ""; int dotIndex = filename.lastIndexOf('.'); if (dotIndex > 0) { baseName = filename.substring(0, dotIndex); extension = filename.substring(dotIndex); } String key = directory + File.separator + baseName + extension; int count = nameCounts.getOrDefault(key, 0); nameCounts.put(key, count + 1); if (count == 0) { return filename; } return baseName + " (" + count + ")" + extension; } public void clearOperations() { operations.clear(); } public void clearFiles() { files.clear(); } public int getFileCount() { return files.size(); } public int getOperationCount() { return operations.size(); } public List<File> getFiles() { return new ArrayList<>(files); } // Result classes public static class RenameResult { private final File originalFile; private final File newFile; private final RenameStatus status; private final String errorMessage; public RenameResult(File originalFile, File newFile, RenameStatus status) { this(originalFile, newFile, status, null); } public RenameResult(File originalFile, File newFile, RenameStatus status, String errorMessage) { this.originalFile = originalFile; this.newFile = newFile; this.status = status; this.errorMessage = errorMessage; } // Getters public File getOriginalFile() { return originalFile; } public File getNewFile() { return newFile; } public RenameStatus getStatus() { return status; } public String getErrorMessage() { return errorMessage; } @Override public String toString() { return String.format("%s -> %s [%s]", originalFile.getName(), newFile != null ? newFile.getName() : "N/A", status); } } public enum RenameStatus { PENDING, SUCCESS, FAILED, ERROR } public enum CaseType { UPPERCASE, LOWERCASE, CAMELCASE, TITLE_CASE } }

Renaming Operations Interface and Implementations

Operation Interface and Base Classes

// Main operation interface interface RenameOperation { String apply(String filename); String getDescription(); } // Abstract base class for common functionality abstract class AbstractRenameOperation implements RenameOperation { protected final String name; protected AbstractRenameOperation(String name) { this.name = name; } @Override public String getDescription() { return name; } protected String getBaseName(String filename) { int dotIndex = filename.lastIndexOf('.'); return dotIndex > 0 ? filename.substring(0, dotIndex) : filename; } protected String getExtension(String filename) { int dotIndex = filename.lastIndexOf('.'); return dotIndex > 0 ? filename.substring(dotIndex) : ""; } } // Replace text operation class ReplaceOperation extends AbstractRenameOperation { private final String search; private final String replacement; public ReplaceOperation(String search, String replacement) { super("Replace '" + search + "' with '" + replacement + "'"); this.search = search; this.replacement = replacement; } @Override public String apply(String filename) { String baseName = getBaseName(filename); String extension = getExtension(filename); String newBaseName = baseName.replace(search, replacement); return newBaseName + extension; } } // Regex-based replacement operation class RegexOperation extends AbstractRenameOperation { private final Pattern pattern; private final String replacement; public RegexOperation(String regex, String replacement) { super("Regex replace '" + regex + "' with '" + replacement + "'"); this.pattern = Pattern.compile(regex); this.replacement = replacement; } @Override public String apply(String filename) { String baseName = getBaseName(filename); String extension = getExtension(filename); Matcher matcher = pattern.matcher(baseName); String newBaseName = matcher.replaceAll(replacement); return newBaseName + extension; } } // Add prefix operation class PrefixOperation extends AbstractRenameOperation { private final String prefix; public PrefixOperation(String prefix) { super("Add prefix '" + prefix + "'"); this.prefix = prefix; } @Override public String apply(String filename) { String baseName = getBaseName(filename); String extension = getExtension(filename); return prefix + baseName + extension; } } // Add suffix operation class SuffixOperation extends AbstractRenameOperation { private final String suffix; public SuffixOperation(String suffix) { super("Add suffix '" + suffix + "'"); this.suffix = suffix; } @Override public String apply(String filename) { String baseName = getBaseName(filename); String extension = getExtension(filename); return baseName + suffix + extension; } } // Case conversion operation class CaseOperation extends AbstractRenameOperation { private final BatchFileRenamer.CaseType caseType; public CaseOperation(BatchFileRenamer.CaseType caseType) { super("Convert to " + caseType.toString().toLowerCase()); this.caseType = caseType; } @Override public String apply(String filename) { String baseName = getBaseName(filename); String extension = getExtension(filename); String newBaseName; switch (caseType) { case UPPERCASE: newBaseName = baseName.toUpperCase(); break; case LOWERCASE: newBaseName = baseName.toLowerCase(); break; case CAMELCASE: newBaseName = toCamelCase(baseName); break; case TITLE_CASE: newBaseName = toTitleCase(baseName); break; default: newBaseName = baseName; } return newBaseName + extension; } private String toCamelCase(String text) { if (text == null || text.isEmpty()) { return text; } String[] words = text.split("[\\s_\\-]+"); StringBuilder result = new StringBuilder(); for (int i = 0; i < words.length; i++) { String word = words[i]; if (!word.isEmpty()) { if (i == 0) { result.append(word.toLowerCase()); } else { result.append(Character.toUpperCase(word.charAt(0))) .append(word.substring(1).toLowerCase()); } } } return result.toString(); } private String toTitleCase(String text) { if (text == null || text.isEmpty()) { return text; } String[] words = text.split("[\\s_\\-]+"); StringBuilder result = new StringBuilder(); for (String word : words) { if (!word.isEmpty()) { if (result.length() > 0) { result.append(" "); } result.append(Character.toUpperCase(word.charAt(0))) .append(word.substring(1).toLowerCase()); } } return result.toString(); } } // Sequential numbering operation class SequentialNumberingOperation extends AbstractRenameOperation { private final String prefix; private final String suffix; private final int startNumber; private final int digits; private int currentNumber; public SequentialNumberingOperation(String prefix, String suffix, int startNumber, int digits) { super("Sequential numbering starting from " + startNumber); this.prefix = prefix != null ? prefix : ""; this.suffix = suffix != null ? suffix : ""; this.startNumber = startNumber; this.digits = Math.max(1, digits); this.currentNumber = startNumber; } @Override public String apply(String filename) { String baseName = getBaseName(filename); String extension = getExtension(filename); String numberStr = String.format("%0" + digits + "d", currentNumber); String newBaseName = prefix + baseName + suffix + " " + numberStr; currentNumber++; return newBaseName + extension; } public void reset() { currentNumber = startNumber; } } // Extension change operation class ExtensionChangeOperation extends AbstractRenameOperation { private final String newExtension; public ExtensionChangeOperation(String newExtension) { super("Change extension to '" + newExtension + "'"); this.newExtension = newExtension.startsWith(".") ? newExtension : "." + newExtension; } @Override public String apply(String filename) { String baseName = getBaseName(filename); return baseName + newExtension; } } // Remove characters operation class RemoveCharactersOperation extends AbstractRenameOperation { private final String charactersToRemove; public RemoveCharactersOperation(String charactersToRemove) { super("Remove characters: '" + charactersToRemove + "'"); this.charactersToRemove = charactersToRemove; } @Override public String apply(String filename) { String baseName = getBaseName(filename); String extension = getExtension(filename); String newBaseName = baseName; for (char c : charactersToRemove.toCharArray()) { newBaseName = newBaseName.replace(String.valueOf(c), ""); } return newBaseName + extension; } } // Truncate operation class TruncateOperation extends AbstractRenameOperation { private final int maxLength; public TruncateOperation(int maxLength) { super("Truncate to " + maxLength + " characters"); this.maxLength = maxLength; } @Override public String apply(String filename) { String baseName = getBaseName(filename); String extension = getExtension(filename); if (baseName.length() <= maxLength) { return filename; } String newBaseName = baseName.substring(0, maxLength); return newBaseName + extension; } }

Advanced File Filtering System

File Filter Implementation

import java.io.File; import java.io.FileFilter; import java.util.function.Predicate; // Advanced file filter system public class AdvancedFileFilter implements FileFilter { private final List<Predicate<File>> predicates; private boolean includeMode = true; // true = include, false = exclude public AdvancedFileFilter() { this.predicates = new ArrayList<>(); } public static AdvancedFileFilter create() { return new AdvancedFileFilter(); } public AdvancedFileFilter include() { this.includeMode = true; return this; } public AdvancedFileFilter exclude() { this.includeMode = false; return this; } public AdvancedFileFilter byExtension(String... extensions) { Predicate<File> extensionPredicate = file -> { String filename = file.getName().toLowerCase(); for (String ext : extensions) { String lowerExt = ext.toLowerCase(); if (!lowerExt.startsWith(".")) { lowerExt = "." + lowerExt; } if (filename.endsWith(lowerExt)) { return true; } } return false; }; predicates.add(extensionPredicate); return this; } public AdvancedFileFilter byNamePattern(String pattern) { Predicate<File> namePredicate = file -> { String filename = file.getName(); return filename.matches(pattern); }; predicates.add(namePredicate); return this; } public AdvancedFileFilter byNameContains(String text) { Predicate<File> containsPredicate = file -> file.getName().toLowerCase().contains(text.toLowerCase()); predicates.add(containsPredicate); return this; } public AdvancedFileFilter bySizeRange(long minSize, long maxSize) { Predicate<File> sizePredicate = file -> { long size = file.length(); return size >= minSize && size <= maxSize; }; predicates.add(sizePredicate); return this; } public AdvancedFileFilter byMinSize(long minSize) { return bySizeRange(minSize, Long.MAX_VALUE); } public AdvancedFileFilter byMaxSize(long maxSize) { return bySizeRange(0, maxSize); } public AdvancedFileFilter byLastModified(long from, long to) { Predicate<File> timePredicate = file -> { long lastModified = file.lastModified(); return lastModified >= from && lastModified <= to; }; predicates.add(timePredicate); return this; } public AdvancedFileFilter modifiedAfter(long timestamp) { return byLastModified(timestamp, Long.MAX_VALUE); } public AdvancedFileFilter modifiedBefore(long timestamp) { return byLastModified(0, timestamp); } public AdvancedFileFilter hiddenFiles(boolean includeHidden) { Predicate<File> hiddenPredicate = file -> includeHidden == file.isHidden(); predicates.add(hiddenPredicate); return this; } @Override public boolean accept(File file) { if (!file.isFile()) { return false; } if (predicates.isEmpty()) { return true; } boolean matchesAll = predicates.stream().allMatch(predicate -> predicate.test(file)); return includeMode ? matchesAll : !matchesAll; } public List<File> filterFiles(File[] files) { return Arrays.stream(files) .filter(this::accept) .collect(Collectors.toList()); } public List<File> filterFiles(List<File> files) { return files.stream() .filter(this::accept) .collect(Collectors.toList()); } }

GUI Application (Swing)

Main GUI Interface

import javax.swing.*; import javax.swing.table.*; import java.awt.*; import java.awt.event.*; import java.io.File; import java.util.List; public class BatchFileRenamerGUI extends JFrame { private final BatchFileRenamer renamer; private DefaultTableModel tableModel; private JTable filesTable; private JTextArea previewArea; private JLabel statusLabel; public BatchFileRenamerGUI() { this.renamer = new BatchFileRenamer(); initializeUI(); } private void initializeUI() { setTitle("Batch File Renamer"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(1000, 700); setLocationRelativeTo(null); createMenuBar(); createMainPanel(); createStatusBar(); setVisible(true); } private void createMenuBar() { JMenuBar menuBar = new JMenuBar(); // File menu JMenu fileMenu = new JMenu("File"); JMenuItem addFilesItem = new JMenuItem("Add Files..."); JMenuItem addFolderItem = new JMenuItem("Add Folder..."); JMenuItem clearFilesItem = new JMenuItem("Clear Files"); JMenuItem exitItem = new JMenuItem("Exit"); addFilesItem.addActionListener(e -> addFiles()); addFolderItem.addActionListener(e -> addFolder()); clearFilesItem.addActionListener(e -> clearFiles()); exitItem.addActionListener(e -> System.exit(0)); fileMenu.add(addFilesItem); fileMenu.add(addFolderItem); fileMenu.addSeparator(); fileMenu.add(clearFilesItem); fileMenu.addSeparator(); fileMenu.add(exitItem); // Operations menu JMenu operationsMenu = new JMenu("Operations"); JMenuItem replaceItem = new JMenuItem("Replace Text..."); JMenuItem regexItem = new JMenuItem("Regex Replace..."); JMenuItem prefixItem = new JMenuItem("Add Prefix..."); JMenuItem suffixItem = new JMenuItem("Add Suffix..."); JMenuItem caseItem = new JMenuItem("Change Case..."); JMenuItem numberingItem = new JMenuItem("Sequential Numbering..."); JMenuItem extensionItem = new JMenuItem("Change Extension..."); JMenuItem clearOpsItem = new JMenuItem("Clear Operations"); replaceItem.addActionListener(e -> showReplaceDialog()); regexItem.addActionListener(e -> showRegexDialog()); prefixItem.addActionListener(e -> showPrefixDialog()); suffixItem.addActionListener(e -> showSuffixDialog()); caseItem.addActionListener(e -> showCaseDialog()); numberingItem.addActionListener(e -> showNumberingDialog()); extensionItem.addActionListener(e -> showExtensionDialog()); clearOpsItem.addActionListener(e -> clearOperations()); operationsMenu.add(replaceItem); operationsMenu.add(regexItem); operationsMenu.addSeparator(); operationsMenu.add(prefixItem); operationsMenu.add(suffixItem); operationsMenu.add(caseItem); operationsMenu.addSeparator(); operationsMenu.add(numberingItem); operationsMenu.add(extensionItem); operationsMenu.addSeparator(); operationsMenu.add(clearOpsItem); menuBar.add(fileMenu); menuBar.add(operationsMenu); setJMenuBar(menuBar); } private void createMainPanel() { JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); splitPane.setResizeWeight(0.6); // Upper panel - Files table and operations JPanel upperPanel = new JPanel(new BorderLayout()); // Files table String[] columnNames = {"Original Name", "New Name", "Status", "Path"}; tableModel = new DefaultTableModel(columnNames, 0) { @Override public boolean isCellEditable(int row, int column) { return false; } }; filesTable = new JTable(tableModel); JScrollPane tableScrollPane = new JScrollPane(filesTable); // Operations panel JPanel operationsPanel = new JPanel(new FlowLayout()); JButton previewButton = new JButton("Preview"); JButton executeButton = new JButton("Execute Rename"); JButton clearButton = new JButton("Clear All"); previewButton.addActionListener(e -> previewRename()); executeButton.addActionListener(e -> executeRename()); clearButton.addActionListener(e -> clearAll()); operationsPanel.add(previewButton); operationsPanel.add(executeButton); operationsPanel.add(clearButton); upperPanel.add(new JLabel("Files to Rename:"), BorderLayout.NORTH); upperPanel.add(tableScrollPane, BorderLayout.CENTER); upperPanel.add(operationsPanel, BorderLayout.SOUTH); // Lower panel - Preview JPanel lowerPanel = new JPanel(new BorderLayout()); previewArea = new JTextArea(10, 80); previewArea.setEditable(false); previewArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12)); JScrollPane previewScrollPane = new JScrollPane(previewArea); lowerPanel.add(new JLabel("Preview:"), BorderLayout.NORTH); lowerPanel.add(previewScrollPane, BorderLayout.CENTER); splitPane.setTopComponent(upperPanel); splitPane.setBottomComponent(lowerPanel); add(splitPane, BorderLayout.CENTER); } private void createStatusBar() { statusLabel = new JLabel("Ready"); statusLabel.setBorder(BorderFactory.createEtchedBorder()); add(statusLabel, BorderLayout.SOUTH); } private void addFiles() { JFileChooser fileChooser = new JFileChooser(); fileChooser.setMultiSelectionEnabled(true); fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); int result = fileChooser.showOpenDialog(this); if (result == JFileChooser.APPROVE_OPTION) { File[] selectedFiles = fileChooser.getSelectedFiles(); for (File file : selectedFiles) { try { renamer.addFile(file); addFileToTable(file); } catch (IllegalArgumentException e) { JOptionPane.showMessageDialog(this, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); } } updateStatus(); } } private void addFolder() { JFileChooser fileChooser = new JFileChooser(); fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); int result = fileChooser.showOpenDialog(this); if (result == JFileChooser.APPROVE_OPTION) { File directory = fileChooser.getSelectedFile(); // Show filter dialog AdvancedFileFilter filter = showFilterDialog(); if (filter != null) { try { renamer.addFilesFromDirectory(directory, true); // Apply filter List<File> filteredFiles = filter.filterFiles(renamer.getFiles()); renamer.clearFiles(); renamer.addFiles(filteredFiles); refreshFileTable(); updateStatus(); } catch (Exception e) { JOptionPane.showMessageDialog(this, "Error adding files: " + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); } } } } private AdvancedFileFilter showFilterDialog() { JDialog filterDialog = new JDialog(this, "File Filter", true); filterDialog.setLayout(new BorderLayout()); JPanel contentPanel = new JPanel(new GridLayout(0, 2, 5, 5)); JTextField extensionField = new JTextField(); JTextField namePatternField = new JTextField(); JTextField minSizeField = new JTextField(); JTextField maxSizeField = new JTextField(); contentPanel.add(new JLabel("Extensions (comma-separated):")); contentPanel.add(extensionField); contentPanel.add(new JLabel("Name pattern (regex):")); contentPanel.add(namePatternField); contentPanel.add(new JLabel("Min size (bytes):")); contentPanel.add(minSizeField); contentPanel.add(new JLabel("Max size (bytes):")); contentPanel.add(maxSizeField); JPanel buttonPanel = new JPanel(); JButton okButton = new JButton("OK"); JButton cancelButton = new JButton("Cancel"); okButton.addActionListener(e -> filterDialog.dispose()); cancelButton.addActionListener(e -> { filterDialog.dispose(); }); buttonPanel.add(okButton); buttonPanel.add(cancelButton); filterDialog.add(contentPanel, BorderLayout.CENTER); filterDialog.add(buttonPanel, BorderLayout.SOUTH); filterDialog.pack(); filterDialog.setLocationRelativeTo(this); filterDialog.setVisible(true); // Build filter based on input AdvancedFileFilter filter = AdvancedFileFilter.create(); String extensions = extensionField.getText().trim(); if (!extensions.isEmpty()) { String[] extArray = extensions.split("\\s*,\\s*"); filter.byExtension(extArray); } String pattern = namePatternField.getText().trim(); if (!pattern.isEmpty()) { filter.byNamePattern(pattern); } try { String minSizeStr = minSizeField.getText().trim(); if (!minSizeStr.isEmpty()) { filter.byMinSize(Long.parseLong(minSizeStr)); } String maxSizeStr = maxSizeField.getText().trim(); if (!maxSizeStr.isEmpty()) { filter.byMaxSize(Long.parseLong(maxSizeStr)); } } catch (NumberFormatException e) { JOptionPane.showMessageDialog(this, "Invalid size format", "Error", JOptionPane.ERROR_MESSAGE); return null; } return filter; } private void addFileToTable(File file) { tableModel.addRow(new Object[]{ file.getName(), file.getName(), "Pending", file.getParent() }); } private void refreshFileTable() { tableModel.setRowCount(0); for (File file : renamer.getFiles()) { addFileToTable(file); } } private void clearFiles() { renamer.clearFiles(); tableModel.setRowCount(0); updateStatus(); } private void clearOperations() { renamer.clearOperations(); previewArea.setText(""); updateStatus(); } private void clearAll() { clearFiles(); clearOperations(); } private void updateStatus() { statusLabel.setText(String.format("Files: %d | Operations: %d", renamer.getFileCount(), renamer.getOperationCount())); } // Operation dialogs private void showReplaceDialog() { JTextField searchField = new JTextField(20); JTextField replaceField = new JTextField(20); Object[] message = { "Search for:", searchField, "Replace with:", replaceField }; int option = JOptionPane.showConfirmDialog(this, message, "Replace Text", JOptionPane.OK_CANCEL_OPTION); if (option == JOptionPane.OK_OPTION) { String search = searchField.getText(); String replacement = replaceField.getText(); if (!search.isEmpty()) { renamer.addReplaceOperation(search, replacement); updatePreview(); updateStatus(); } } } private void showRegexDialog() { JTextField regexField = new JTextField(20); JTextField replaceField = new JTextField(20); Object[] message = { "Regular expression:", regexField, "Replacement:", replaceField }; int option = JOptionPane.showConfirmDialog(this, message, "Regex Replace", JOptionPane.OK_CANCEL_OPTION); if (option == JOptionPane.OK_OPTION) { String regex = regexField.getText(); String replacement = replaceField.getText(); if (!regex.isEmpty()) { renamer.addRegexOperation(regex, replacement); updatePreview(); updateStatus(); } } } private void showPrefixDialog() { String prefix = JOptionPane.showInputDialog(this, "Enter prefix:", "Add Prefix", JOptionPane.QUESTION_MESSAGE); if (prefix != null && !prefix.trim().isEmpty()) { renamer.addPrefixOperation(prefix.trim()); updatePreview(); updateStatus(); } } private void showSuffixDialog() { String suffix = JOptionPane.showInputDialog(this, "Enter suffix:", "Add Suffix", JOptionPane.QUESTION_MESSAGE); if (suffix != null && !suffix.trim().isEmpty()) { renamer.addSuffixOperation(suffix.trim()); updatePreview(); updateStatus(); } } private void showCaseDialog() { String[] options = {"UPPERCASE", "lowercase", "CamelCase", "Title Case"}; String choice = (String) JOptionPane.showInputDialog(this, "Select case conversion:", "Change Case", JOptionPane.QUESTION_MESSAGE, null, options, options[0]); if (choice != null) { BatchFileRenamer.CaseType caseType = BatchFileRenamer.CaseType.valueOf( choice.toUpperCase().replace(" ", "_")); renamer.addCaseOperation(caseType); updatePreview(); updateStatus(); } } private void showNumberingDialog() { JTextField prefixField = new JTextField(10); JTextField suffixField = new JTextField(10); JSpinner startSpinner = new JSpinner(new SpinnerNumberModel(1, 1, 10000, 1)); JSpinner digitsSpinner = new JSpinner(new SpinnerNumberModel(2, 1, 10, 1)); Object[] message = { "Prefix:", prefixField, "Suffix:", suffixField, "Start number:", startSpinner, "Number of digits:", digitsSpinner }; int option = JOptionPane.showConfirmDialog(this, message, "Sequential Numbering", JOptionPane.OK_CANCEL_OPTION); if (option == JOptionPane.OK_OPTION) { String prefix = prefixField.getText(); String suffix = suffixField.getText(); int startNumber = (Integer) startSpinner.getValue(); int digits = (Integer) digitsSpinner.getValue(); renamer.addSequentialNumbering(prefix, suffix, startNumber, digits); updatePreview(); updateStatus(); } } private void showExtensionDialog() { String newExtension = JOptionPane.showInputDialog(this, "Enter new extension (with or without dot):", "Change Extension", JOptionPane.QUESTION_MESSAGE); if (newExtension != null && !newExtension.trim().isEmpty()) { renamer.addExtensionChange(newExtension.trim()); updatePreview(); updateStatus(); } } private void updatePreview() { List<BatchFileRenamer.RenameResult> preview = renamer.previewRename(); StringBuilder sb = new StringBuilder(); sb.append("PREVIEW - Changes to be made:\n\n"); for (BatchFileRenamer.RenameResult result : preview) { sb.append(String.format("%-30s -> %-30s\n", result.getOriginalFile().getName(), result.getNewFile().getName())); } previewArea.setText(sb.toString()); } private void previewRename() { if (renamer.getFileCount() == 0) { JOptionPane.showMessageDialog(this, "No files to rename", "Warning", JOptionPane.WARNING_MESSAGE); return; } updatePreview(); } private void executeRename() { if (renamer.getFileCount() == 0) { JOptionPane.showMessageDialog(this, "No files to rename", "Warning", JOptionPane.WARNING_MESSAGE); return; } if (renamer.getOperationCount() == 0) { JOptionPane.showMessageDialog(this, "No operations defined", "Warning", JOptionPane.WARNING_MESSAGE); return; } int confirm = JOptionPane.showConfirmDialog(this, "Are you sure you want to rename " + renamer.getFileCount() + " files?", "Confirm Rename", JOptionPane.YES_NO_OPTION); if (confirm == JOptionPane.YES_OPTION) { List<BatchFileRenamer.RenameResult> results = renamer.executeRename(); int successCount = 0; int errorCount = 0; StringBuilder resultText = new StringBuilder(); resultText.append("RENAME RESULTS:\n\n"); for (BatchFileRenamer.RenameResult result : results) { switch (result.getStatus()) { case SUCCESS: successCount++; resultText.append("✓ "); break; case FAILED: case ERROR: errorCount++; resultText.append("✗ "); break; default: resultText.append("? "); } resultText.append(String.format("%s -> %s", result.getOriginalFile().getName(), result.getNewFile() != null ? result.getNewFile().getName() : "N/A")); if (result.getErrorMessage() != null) { resultText.append(" [Error: ").append(result.getErrorMessage()).append("]"); } resultText.append("\n"); } resultText.append("\nSummary: ").append(successCount) .append(" successful, ").append(errorCount).append(" failed"); previewArea.setText(resultText.toString()); refreshFileTable(); JOptionPane.showMessageDialog(this, String.format("Rename completed: %d successful, %d failed", successCount, errorCount), "Rename Complete", JOptionPane.INFORMATION_MESSAGE); } } public static void main(String[] args) { SwingUtilities.invokeLater(() -> { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeel()); } catch (Exception e) { e.printStackTrace(); } new BatchFileRenamerGUI(); }); } }

Command Line Interface

CLI Version

import java.io.*; import java.util.*; public class BatchFileRenamerCLI { private final BatchFileRenamer renamer; private final Scanner scanner; public BatchFileRenamerCLI() { this.renamer = new BatchFileRenamer(); this.scanner = new Scanner(System.in); } public void start() { System.out.println("=== Batch File Renamer CLI ==="); System.out.println(); boolean running = true; while (running) { showMainMenu(); String choice = scanner.nextLine().trim(); switch (choice) { case "1": addFilesInteractive(); break; case "2": addFolderInteractive(); break; case "3": showOperationsMenu(); break; case "4": previewRename(); break; case "5": executeRename(); break; case "6": showCurrentState(); break; case "7": clearAll(); break; case "0": running = false; break; default: System.out.println("Invalid choice. Please try again."); } } System.out.println("Goodbye!"); } private void showMainMenu() { System.out.println("\n--- Main Menu ---"); System.out.println("1. Add files"); System.out.println("2. Add folder"); System.out.println("3. Operations"); System.out.println("4. Preview rename"); System.out.println("5. Execute rename"); System.out.println("6. Show current state"); System.out.println("7. Clear all"); System.out.println("0. Exit"); System.out.print("Choose an option: "); } private void addFilesInteractive() { System.out.print("Enter file paths (comma-separated): "); String input = scanner.nextLine(); String[] filePaths = input.split("\\s*,\\s*"); int addedCount = 0; for (String path : filePaths) { File file = new File(path.trim()); if (file.exists() && file.isFile()) { renamer.addFile(file); addedCount++; System.out.println("Added: " + file.getName()); } else { System.out.println("File not found: " + path); } } System.out.println("Added " + addedCount + " files."); } private void addFolderInteractive() { System.out.print("Enter folder path: "); String path = scanner.nextLine().trim(); File folder = new File(path); if (!folder.exists() || !folder.isDirectory()) { System.out.println("Folder not found: " + path); return; } System.out.print("Recursive (y/n)? "); boolean recursive = scanner.nextLine().trim().equalsIgnoreCase("y"); try { renamer.addFilesFromDirectory(folder, recursive); System.out.println("Added " + renamer.getFileCount() + " files from folder."); } catch (Exception e) { System.out.println("Error adding files: " + e.getMessage()); } } private void showOperationsMenu() { boolean inMenu = true; while (inMenu) { System.out.println("\n--- Operations Menu ---"); System.out.println("1. Replace text"); System.out.println("2. Regex replace"); System.out.println("3. Add prefix"); System.out.println("4. Add suffix"); System.out.println("5. Change case"); System.out.println("6. Sequential numbering"); System.out.println("7. Change extension"); System.out.println("8. Remove characters"); System.out.println("9. Show current operations"); System.out.println("0. Back to main menu"); System.out.print("Choose an option: "); String choice = scanner.nextLine().trim(); switch (choice) { case "1": addReplaceOperation(); break; case "2": addRegexOperation(); break; case "3": addPrefixOperation(); break; case "4": addSuffixOperation(); break; case "5": addCaseOperation(); break; case "6": addNumberingOperation(); break; case "7": addExtensionOperation(); break; case "8": addRemoveCharsOperation(); break; case "9": showCurrentOperations(); break; case "0": inMenu = false; break; default: System.out.println("Invalid choice."); } } } private void addReplaceOperation() { System.out.print("Enter text to search for: "); String search = scanner.nextLine(); System.out.print("Enter replacement text: "); String replacement = scanner.nextLine(); renamer.addReplaceOperation(search, replacement); System.out.println("Added replace operation."); } private void addRegexOperation() { System.out.print("Enter regular expression: "); String regex = scanner.nextLine(); System.out.print("Enter replacement: "); String replacement = scanner.nextLine(); renamer.addRegexOperation(regex, replacement); System.out.println("Added regex operation."); } private void addPrefixOperation() { System.out.print("Enter prefix: "); String prefix = scanner.nextLine(); renamer.addPrefixOperation(prefix); System.out.println("Added prefix operation."); } private void addSuffixOperation() { System.out.print("Enter suffix: "); String suffix = scanner.nextLine(); renamer.addSuffixOperation(suffix); System.out.println("Added suffix operation."); } private void addCaseOperation() { System.out.println("Case options:"); System.out.println("1. UPPERCASE"); System.out.println("2. lowercase"); System.out.println("3. CamelCase"); System.out.println("4. Title Case"); System.out.print("Choose case type: "); String choice = scanner.nextLine().trim(); BatchFileRenamer.CaseType caseType; switch (choice) { case "1": caseType = BatchFileRenamer.CaseType.UPPERCASE; break; case "2": caseType = BatchFileRenamer.CaseType.LOWERCASE; break; case "3": caseType = BatchFileRenamer.CaseType.CAMELCASE; break; case "4": caseType = BatchFileRenamer.CaseType.TITLE_CASE; break; default: System.out.println("Invalid choice. Using UPPERCASE."); caseType = BatchFileRenamer.CaseType.UPPERCASE; } renamer.addCaseOperation(caseType); System.out.println("Added case operation."); } private void addNumberingOperation() { System.out.print("Enter prefix (optional): "); String prefix = scanner.nextLine(); System.out.print("Enter suffix (optional): "); String suffix = scanner.nextLine(); System.out.print("Start number (default 1): "); String startStr = scanner.nextLine(); System.out.print("Number of digits (default 2): "); String digitsStr = scanner.nextLine(); int start = startStr.isEmpty() ? 1 : Integer.parseInt(startStr); int digits = digitsStr.isEmpty() ? 2 : Integer.parseInt(digitsStr); renamer.addSequentialNumbering(prefix, suffix, start, digits); System.out.println("Added numbering operation."); } private void addExtensionOperation() { System.out.print("Enter new extension: "); String extension = scanner.nextLine(); renamer.addExtensionChange(extension); System.out.println("Added extension change operation."); } private void addRemoveCharsOperation() { System.out.print("Enter characters to remove: "); String chars = scanner.nextLine(); renamer.addCustomOperation(new RemoveCharactersOperation(chars)); System.out.println("Added remove characters operation."); } private void showCurrentOperations() { System.out.println("\nCurrent operations:"); // Note: In a real implementation, you'd want to store operation descriptions System.out.println("Operations count: " + renamer.getOperationCount()); } private void previewRename() { if (renamer.getFileCount() == 0) { System.out.println("No files to rename."); return; } List<BatchFileRenamer.RenameResult> preview = renamer.previewRename(); System.out.println("\n--- Preview ---"); for (BatchFileRenamer.RenameResult result : preview) { System.out.printf("%s -> %s\n", result.getOriginalFile().getName(), result.getNewFile().getName()); } } private void executeRename() { if (renamer.getFileCount() == 0) { System.out.println("No files to rename."); return; } if (renamer.getOperationCount() == 0) { System.out.println("No operations defined."); return; } System.out.print("Are you sure you want to rename " + renamer.getFileCount() + " files? (y/n): "); String confirm = scanner.nextLine().trim(); if (confirm.equalsIgnoreCase("y")) { List<BatchFileRenamer.RenameResult> results = renamer.executeRename(); int successCount = 0; int errorCount = 0; System.out.println("\n--- Results ---"); for (BatchFileRenamer.RenameResult result : results) { switch (result.getStatus()) { case SUCCESS: successCount++; System.out.printf("✓ %s -> %s\n", result.getOriginalFile().getName(), result.getNewFile().getName()); break; case FAILED: case ERROR: errorCount++; System.out.printf("✗ %s -> %s", result.getOriginalFile().getName(), result.getNewFile() != null ? result.getNewFile().getName() : "N/A"); if (result.getErrorMessage() != null) { System.out.print(" [Error: " + result.getErrorMessage() + "]"); } System.out.println(); break; } } System.out.printf("\nSummary: %d successful, %d failed\n", successCount, errorCount); } } private void showCurrentState() { System.out.println("\n--- Current State ---"); System.out.println("Files: " + renamer.getFileCount()); System.out.println("Operations: " + renamer.getOperationCount()); if (renamer.getFileCount() > 0) { System.out.println("\nFiles:"); for (File file : renamer.getFiles()) { System.out.println(" " + file.getName()); } } } private void clearAll() { renamer.clearFiles(); renamer.clearOperations(); System.out.println("Cleared all files and operations."); } public static void main(String[] args) { new BatchFileRenamerCLI().start(); } }

Usage Examples

Basic Usage Examples

public class BatchFileRenamerExamples { public static void main(String[] args) { // Example 1: Simple text replacement example1(); // Example 2: Multiple operations example2(); // Example 3: Sequential numbering example3(); // Example 4: Using filters example4(); } private static void example1() { System.out.println("=== Example 1: Simple Text Replacement ==="); BatchFileRenamer renamer = new BatchFileRenamer(); // Add some test files (in real usage, these would be actual files) renamer.addFile(new File("photo1.jpg")); renamer.addFile(new File("photo2.jpg")); renamer.addFile(new File("photo3.jpg")); // Replace "photo" with "image" renamer.addReplaceOperation("photo", "image"); // Preview changes List<BatchFileRenamer.RenameResult> preview = renamer.previewRename(); for (BatchFileRenamer.RenameResult result : preview) { System.out.println(result.getOriginalFile().getName() + " -> " + result.getNewFile().getName()); } } private static void example2() { System.out.println("\n=== Example 2: Multiple Operations ==="); BatchFileRenamer renamer = new BatchFileRenamer(); renamer.addFile(new File("MY_DOCUMENT_001.txt")); renamer.addFile(new File("ANOTHER_FILE_002.doc")); // Convert to lowercase renamer.addCaseOperation(BatchFileRenamer.CaseType.LOWERCASE); // Replace underscores with spaces renamer.addReplaceOperation("_", " "); // Add prefix renamer.addPrefixOperation("processed_"); List<BatchFileRenamer.RenameResult> preview = renamer.previewRename(); for (BatchFileRenamer.RenameResult result : preview) { System.out.println(result.getOriginalFile().getName() + " -> " + result.getNewFile().getName()); } } private static void example3() { System.out.println("\n=== Example 3: Sequential Numbering ==="); BatchFileRenamer renamer = new BatchFileRenamer(); renamer.addFile(new File("image.jpg")); renamer.addFile(new File("image.jpg")); renamer.addFile(new File("image.jpg")); // Add sequential numbering renamer.addSequentialNumbering("vacation_", "", 1, 3); List<BatchFileRenamer.RenameResult> preview = renamer.previewRename(); for (BatchFileRenamer.RenameResult result : preview) { System.out.println(result.getOriginalFile().getName() + " -> " + result.getNewFile().getName()); } } private static void example4() { System.out.println("\n=== Example 4: Using Filters ==="); // Create a directory with test files File testDir = new File("test_files"); testDir.mkdir(); try { // Create some test files new File(testDir, "document1.pdf").createNewFile(); new File(testDir, "image1.jpg").createNewFile(); new File(testDir, "image2.png").createNewFile(); new File(testDir, "data.txt").createNewFile(); // Use advanced filter AdvancedFileFilter filter = AdvancedFileFilter.create() .byExtension("jpg", "png") .byNameContains("image"); File[] allFiles = testDir.listFiles(); List<File> filteredFiles = filter.filterFiles(allFiles); System.out.println("Filtered files:"); for (File file : filteredFiles) { System.out.println(" " + file.getName()); } // Clean up for (File file : allFiles) { file.delete(); } testDir.delete(); } catch (IOException e) { e.printStackTrace(); } } }

Features Summary

This Batch File Renamer provides:

  1. Multiple Renaming Strategies:
  • Text replacement
  • Regex-based replacement
  • Prefix/suffix addition
  • Case conversion
  • Sequential numbering
  • Extension changes
  • Character removal
  • Truncation
  1. File Management:
  • Add individual files
  • Add entire directories (recursive or not)
  • Advanced file filtering
  • Conflict resolution
  1. Safety Features:
  • Preview mode
  • Operation validation
  • Error handling
  • Undo capability (through backup)
  1. Multiple Interfaces:
  • Graphical user interface (Swing)
  • Command-line interface
  • Programmatic API
  1. Extensibility:
  • Custom operation interface
  • Pluggable filters
  • Modular design

The tool is suitable for both simple file renaming tasks and complex batch processing scenarios.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper