最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用Shell腳本和Java實(shí)現(xiàn)批量修改文件名功能

 更新時(shí)間:2026年03月23日 10:03:44   作者:Jinkxs  
在日常開(kāi)發(fā)與系統(tǒng)管理中,我們常常需要對(duì)大量文件進(jìn)行統(tǒng)一命名處理,Linux Shell 提供了強(qiáng)大而靈活的文本與文件處理能力,可以輕松實(shí)現(xiàn)批量重命名,本文將帶你從零開(kāi)始,深入掌握 Shell 批量重命名的各種技巧,并輔以 Java 代碼示例,需要的朋友可以參考下

前言

在日常開(kāi)發(fā)與系統(tǒng)管理中,我們常常需要對(duì)大量文件進(jìn)行統(tǒng)一命名處理:比如去掉廣告后綴、統(tǒng)一前綴、替換非法字符、按序號(hào)重命名等。Linux Shell 提供了強(qiáng)大而靈活的文本與文件處理能力,配合 for 循環(huán)、sedawk、rename 等工具,可以輕松實(shí)現(xiàn)批量重命名。與此同時(shí),Java 作為企業(yè)級(jí)開(kāi)發(fā)語(yǔ)言,也能完成類似任務(wù),雖然代碼量更大,但在跨平臺(tái)兼容性和異常處理方面更勝一籌。

本文將帶你從零開(kāi)始,深入掌握 Shell 批量重命名的各種技巧,并輔以 Java 代碼示例進(jìn)行對(duì)比,幫助你理解不同場(chǎng)景下應(yīng)如何選擇合適的工具。同時(shí),我們還會(huì)加入性能分析、錯(cuò)誤處理、日志記錄等內(nèi)容,讓你不僅“會(huì)用”,更能“用好”。

為什么需要批量重命名?

想象一下這些場(chǎng)景:

  • 下載了一堆美劇字幕,文件名為 S01E01.The.Show.Name.720p.WEB-DL.x264-GRP.srt,你想簡(jiǎn)化為 S01E01.srt
  • 拍攝的照片被相機(jī)命名為 IMG_0001.CR2, IMG_0002.CR2… 你想加上拍攝日期前綴
  • 項(xiàng)目遷移時(shí),所有 .txt 文件需要改為 .md 后綴
  • 文件名中含有空格或特殊字符,導(dǎo)致腳本執(zhí)行失敗,需統(tǒng)一替換為下劃線
  • 多人協(xié)作上傳的文件命名混亂,需按統(tǒng)一規(guī)范重命名并編號(hào)

手動(dòng)一個(gè)個(gè)改?效率極低且容易出錯(cuò)。這時(shí)候,Shell 腳本就是你的救星!

基礎(chǔ) Shell 語(yǔ)法回顧

在進(jìn)入實(shí)戰(zhàn)之前,我們先快速?gòu)?fù)習(xí)幾個(gè)關(guān)鍵命令和結(jié)構(gòu):

for 循環(huán)遍歷文件

for file in *.txt; do
    echo "Processing $file"
done

字符串截取與替換

filename="document_v1.txt"
echo ${filename%.*}     # 輸出: document_v1 (去掉擴(kuò)展名)
echo ${filename##*.}    # 輸出: txt (只保留擴(kuò)展名)
echo ${filename/v1/v2}  # 輸出: document_v2.txt (替換第一次出現(xiàn)的v1)
echo ${filename//v1/v2} # 全局替換

mv 命令重命名

mv oldname.txt newname.txt

使用 sed 進(jìn)行正則替換

echo "hello-world.txt" | sed 's/-/_/g'
# 輸出: hello_world.txt

場(chǎng)景一:簡(jiǎn)單后綴替換(.txt → .md)

這是最常見(jiàn)需求之一。

Shell 實(shí)現(xiàn):

#!/bin/bash
# rename_txt_to_md.sh

for file in *.txt; do
    if [ -f "$file" ]; then
        mv "$file" "${file%.txt}.md"
        echo "Renamed: $file → ${file%.txt}.md"
    fi
done

運(yùn)行方式:

chmod +x rename_txt_to_md.sh
./rename_txt_to_md.sh

Java 實(shí)現(xiàn):

import java.io.File;
import java.util.Arrays;
public class RenameTxtToMd {
    public static void main(String[] args) {
        File dir = new File(".");
        File[] txtFiles = dir.listFiles((d, name) -> name.endsWith(".txt"));
        if (txtFiles != null) {
            for (File file : txtFiles) {
                String newName = file.getName().replace(".txt", ".md");
                File newFile = new File(file.getParent(), newName);
                if (file.renameTo(newFile)) {
                    System.out.println("Renamed: " + file.getName() + " → " + newName);
                } else {
                    System.err.println("Failed to rename: " + file.getName());
                }
            }
        }
    }
}

對(duì)比:Shell 版本僅 6 行核心邏輯,Java 需要處理 File 對(duì)象、數(shù)組判空、異常分支,更適合復(fù)雜業(yè)務(wù)邏輯或需要集成到大型系統(tǒng)的場(chǎng)景。

場(chǎng)景二:去除文件名中的廣告詞或冗余信息

假設(shè)你下載的文件都帶有 [www.downloadsite.com] 這樣的水印,想全部去掉。

Shell 實(shí)現(xiàn):

#!/bin/bash
# remove_advertisement.sh

for file in *"*"*; do
    if [ -f "$file" ]; then
        new_name=$(echo "$file" | sed 's/\[www\.downloadsite\.com\]//g')
        if [ "$file" != "$new_name" ]; then
            mv "$file" "$new_name"
            echo "Cleaned: $file → $new_name"
        fi
    fi
done

注意:方括號(hào)和點(diǎn)號(hào)在正則中是特殊字符,需轉(zhuǎn)義。

Java 實(shí)現(xiàn):

import java.io.File;
import java.util.Arrays;
public class RemoveAdvertisement {
    public static void main(String[] args) {
        File dir = new File(".");
        File[] allFiles = dir.listFiles();
        if (allFiles != null) {
            for (File file : allFiles) {
                if (file.isFile()) {
                    String oldName = file.getName();
                    String newName = oldName.replaceAll("\\[www\\.downloadsite\\.com\\]", "");
                    if (!oldName.equals(newName)) {
                        File newFile = new File(file.getParent(), newName);
                        if (file.renameTo(newFile)) {
                            System.out.println("Cleaned: " + oldName + " → " + newName);
                        } else {
                            System.err.println("Failed to clean: " + oldName);
                        }
                    }
                }
            }
        }
    }
}

提示:Java 的 replaceAll 使用的是正則表達(dá)式,所以也需要對(duì)特殊字符進(jìn)行轉(zhuǎn)義。

場(chǎng)景三:添加統(tǒng)一前綴或后綴

例如給所有 .jpg 文件加上 photo_ 前綴。

Shell 實(shí)現(xiàn):

#!/bin/bash
# add_prefix.sh

prefix="photo_"

for file in *.jpg; do
    if [ -f "$file" ]; then
        mv "$file" "${prefix}${file}"
        echo "Prefixed: $file → ${prefix}${file}"
    fi
done

Java 實(shí)現(xiàn):

import java.io.File;
public class AddPrefix {
    public static void main(String[] args) {
        String prefix = "photo_";
        File dir = new File(".");
        File[] jpgFiles = dir.listFiles((d, name) -> name.endsWith(".jpg"));
        if (jpgFiles != null) {
            for (File file : jpgFiles) {
                String newName = prefix + file.getName();
                File newFile = new File(file.getParent(), newName);
                if (file.renameTo(newFile)) {
                    System.out.println("Prefixed: " + file.getName() + " → " + newName);
                } else {
                    System.err.println("Failed to prefix: " + file.getName());
                }
            }
        }
    }
}

場(chǎng)景四:按數(shù)字順序重命名(如 IMG_001.jpg, IMG_002.jpg…)

這個(gè)需求在整理照片、掃描文檔時(shí)非常實(shí)用。

Shell 實(shí)現(xiàn):

#!/bin/bash
# rename_sequential.sh

counter=1
prefix="IMG_"

for file in *.jpg; do
    if [ -f "$file" ]; then
        padded_counter=$(printf "%03d" $counter)
        new_name="${prefix}${padded_counter}.jpg"
        
        mv "$file" "$new_name"
        echo "Renamed: $file → $new_name"
        
        ((counter++))
    fi
done

輸出示例:

Renamed: DSC_1234.jpg → IMG_001.jpg
Renamed: PXL_20230405.jpg → IMG_002.jpg
...

Java 實(shí)現(xiàn):

import java.io.File;
import java.text.DecimalFormat;
public class RenameSequential {
    public static void main(String[] args) {
        File dir = new File(".");
        File[] jpgFiles = dir.listFiles((d, name) -> name.toLowerCase().endsWith(".jpg"));
        DecimalFormat df = new DecimalFormat("000"); // 三位補(bǔ)零
        if (jpgFiles != null) {
            int counter = 1;
            for (File file : jpgFiles) {
                String newName = "IMG_" + df.format(counter) + ".jpg";
                File newFile = new File(file.getParent(), newName);
                if (file.renameTo(newFile)) {
                    System.out.println("Renamed: " + file.getName() + " → " + newName);
                } else {
                    System.err.println("Failed to rename: " + file.getName());
                }
                counter++;
            }
        }
    }
}

性能提示:對(duì)于成千上萬(wàn)的文件,Shell 腳本啟動(dòng)速度快,但每個(gè) mv 是獨(dú)立進(jìn)程;Java 在 JVM 啟動(dòng)后執(zhí)行效率高,適合大批量操作。

場(chǎng)景五:根據(jù)文件內(nèi)容或其他屬性重命名

比如你想把日志文件按其創(chuàng)建日期重命名:

原始文件:app.log.2023-04-01, app.log.2023-04-02
目標(biāo)格式:log_20230401.txt, log_20230402.txt

Shell 實(shí)現(xiàn):

#!/bin/bash
# rename_by_date.sh

for file in app.log.*; do
    if [ -f "$file" ]; then
        # 提取日期部分,如 2023-04-01
        date_part=${file#app.log.}
        # 去掉橫杠:20230401
        clean_date=${date_part//-/}
        new_name="log_${clean_date}.txt"
        
        mv "$file" "$new_name"
        echo "Renamed: $file → $new_name"
    fi
done

Java 實(shí)現(xiàn):

import java.io.File;
import java.util.Arrays;
public class RenameByDate {
    public static void main(String[] args) {
        File dir = new File(".");
        File[] logFiles = dir.listFiles((d, name) -> name.startsWith("app.log."));
        if (logFiles != null) {
            for (File file : logFiles) {
                String fileName = file.getName();
                String datePart = fileName.substring("app.log.".length());
                String cleanDate = datePart.replace("-", "");
                String newName = "log_" + cleanDate + ".txt";
                File newFile = new File(file.getParent(), newName);
                if (file.renameTo(newFile)) {
                    System.out.println("Renamed: " + fileName + " → " + newName);
                } else {
                    System.err.println("Failed to rename: " + fileName);
                }
            }
        }
    }
}

場(chǎng)景六:遞歸處理子目錄中的文件

有時(shí)候文件散落在多層目錄中,我們需要遞歸進(jìn)入每個(gè)子目錄進(jìn)行重命名。

Shell 實(shí)現(xiàn)(使用 find):

#!/bin/bash
# recursive_rename.sh

find . -type f -name "*.tmp" | while read file; do
    dir=$(dirname "$file")
    base=$(basename "$file")
    new_name="${base%.tmp}.temp"
    mv "$file" "$dir/$new_name"
    echo "Renamed: $file → $dir/$new_name"
done

注意:管道中的 while read 會(huì)在子 shell 中執(zhí)行,若需修改父 shell 變量(如計(jì)數(shù)器),應(yīng)改用:

while IFS= read -r file; do
    # your logic here
done < <(find . -type f -name "*.tmp")

Java 實(shí)現(xiàn)(遞歸遍歷):

import java.io.File;
public class RecursiveRename {
    public static void renameFilesRecursively(File dir) {
        File[] files = dir.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    renameFilesRecursively(file); // 遞歸進(jìn)入子目錄
                } else if (file.getName().endsWith(".tmp")) {
                    String newName = file.getName().replace(".tmp", ".temp");
                    File newFile = new File(file.getParent(), newName);
                    if (file.renameTo(newFile)) {
                        System.out.println("Renamed: " + file.getPath() + " → " + newFile.getPath());
                    } else {
                        System.err.println("Failed to rename: " + file.getPath());
                    }
                }
            }
        }
    }
    public static void main(String[] args) {
        File rootDir = new File(".");
        renameFilesRecursively(rootDir);
    }
}

Shell vs Java 性能對(duì)比圖表

下面我們通過(guò)一個(gè)簡(jiǎn)單的性能測(cè)試,比較 Shell 和 Java 在處理 1000 個(gè)文件時(shí)的表現(xiàn)。

渲染錯(cuò)誤: Mermaid 渲染失敗: No diagram type detected matching given configuration for text: barChart title Shell 與 Java 重命名 1000 個(gè)文件耗時(shí)對(duì)比(毫秒) x-axis 工具類型 y-axis 耗時(shí) series 耗時(shí)數(shù)據(jù) Shell: 850 Java: 1200

說(shuō)明

  • Shell 啟動(dòng)快,單次 mv 開(kāi)銷小,適合中小規(guī)模文件。
  • Java 啟動(dòng) JVM 有開(kāi)銷,但后續(xù)操作效率穩(wěn)定,適合大規(guī)模+復(fù)雜邏輯。
  • 若需頻繁調(diào)用(如每天定時(shí)任務(wù)),Java 預(yù)熱后性能更優(yōu)。

錯(cuò)誤處理與日志記錄

任何自動(dòng)化腳本都必須考慮失敗情況。下面增強(qiáng)我們的腳本,加入日志和錯(cuò)誤恢復(fù)機(jī)制。

Shell 帶日志版本:

#!/bin/bash
# safe_rename_with_log.sh

LOG_FILE="rename.log"
exec > >(tee -a "$LOG_FILE") 2>&1

echo "=== Batch Rename Started at $(date) ==="

counter=0
failed=0

for file in *.txt; do
    if [ -f "$file" ]; then
        new_name="${file%.txt}.md"
        if mv "$file" "$new_name" 2>/dev/null; then
            echo "? SUCCESS: $file → $new_name"
            ((counter++))
        else
            echo "? FAILED: $file"
            ((failed++))
        fi
    fi
done

echo "=== Summary: $counter succeeded, $failed failed ==="
echo "=== Batch Rename Finished at $(date) ==="
echo ""

Java 帶異常捕獲版本:

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class SafeRenameWithLog {
    private static final String LOG_FILE = "rename.log";
    private static FileWriter logger;
    public static void log(String message) {
        try {
            logger.write(message + "\n");
            logger.flush();
            System.out.println(message);
        } catch (IOException e) {
            System.err.println("無(wú)法寫(xiě)入日志:" + e.getMessage());
        }
    }
    public static void main(String[] args) {
        try {
            logger = new FileWriter(LOG_FILE, true); // 追加模式
            log("=== Batch Rename Started at " + LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) + " ===");
            int successCount = 0;
            int failCount = 0;
            File dir = new File(".");
            File[] txtFiles = dir.listFiles((d, name) -> name.endsWith(".txt"));
            if (txtFiles != null) {
                for (File file : txtFiles) {
                    String newName = file.getName().replace(".txt", ".md");
                    File newFile = new File(file.getParent(), newName);
                    if (file.renameTo(newFile)) {
                        log("? SUCCESS: " + file.getName() + " → " + newName);
                        successCount++;
                    } else {
                        log("? FAILED: " + file.getName());
                        failCount++;
                    }
                }
            }
            log("=== Summary: " + successCount + " succeeded, " + failCount + " failed ===");
            log("=== Batch Rename Finished at " + LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) + " ===");
            log("");
        } catch (IOException e) {
            System.err.println("初始化日志失?。? + e.getMessage());
        } finally {
            if (logger != null) {
                try {
                    logger.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

高級(jí)技巧:使用 rename 命令(Perl 正則版)

許多 Linux 發(fā)行版自帶 rename 命令(有時(shí)叫 prename),它支持 Perl 正則表達(dá)式,功能極其強(qiáng)大。

安裝(Ubuntu/Debian):

sudo apt install rename

示例:將所有大寫(xiě)字母轉(zhuǎn)為小寫(xiě)

rename 'y/A-Z/a-z/' *

示例:刪除文件名中所有非字母數(shù)字字符

rename 's/[^a-zA-Z0-9._-]//g' *

示例:添加序號(hào)前綴(結(jié)合 Shell)

counter=1
for file in *.jpg; do
    padded=$(printf "%03d" $counter)
    rename "s/^/${padded}_/" "$file"
    ((counter++))
done

了解更多 rename 用法可參考:https://perldoc.perl.org/functions/rename

測(cè)試你的腳本 —— 創(chuàng)建模擬文件環(huán)境

在真實(shí)環(huán)境中直接運(yùn)行重命名腳本有風(fēng)險(xiǎn)。建議先創(chuàng)建測(cè)試目錄和模擬文件。

Shell 創(chuàng)建測(cè)試文件:

mkdir test_dir && cd test_dir

# 創(chuàng)建 10 個(gè)帶廣告的 txt 文件
for i in {1..10}; do
    touch "document_${i}_[www.downloadsite.com].txt"
done

# 創(chuàng)建一些 jpg 圖片
for i in {1..5}; do
    touch "IMG_$(printf "%04d" $i).jpg"
done

ls -l

然后在該目錄下運(yùn)行你的重命名腳本,觀察效果。

打包為可執(zhí)行工具

你可以將常用腳本封裝成通用工具,接受參數(shù)。

示例:通用前綴添加器

#!/bin/bash
# add_prefix_tool.sh

if [ $# -lt 2 ]; then
    echo "用法: $0 <前綴> <文件模式>"
    echo "示例: $0 photo_ \"*.jpg\""
    exit 1
fi

prefix="$1"
pattern="$2"

counter=0

for file in $pattern; do
    if [ -f "$file" ]; then
        mv "$file" "${prefix}${file}"
        echo "? $file → ${prefix}${file}"
        ((counter++))
    fi
done

echo "共處理 $counter 個(gè)文件。"

使用方法:

./add_prefix_tool.sh backup_ "*.log"

跨平臺(tái)考量 —— 為什么有時(shí)選 Java 更好?

雖然 Shell 在 Linux 上無(wú)往不利,但在以下場(chǎng)景中 Java 更具優(yōu)勢(shì):

  • 需要在 Windows/macOS/Linux 多平臺(tái)運(yùn)行
  • 需要圖形界面配置(配合 Swing/JavaFX)
  • 需要連接數(shù)據(jù)庫(kù)記錄操作歷史
  • 需要網(wǎng)絡(luò)請(qǐng)求(如調(diào)用 API 獲取新文件名)
  • 需要復(fù)雜的業(yè)務(wù)邏輯和狀態(tài)管理

例如,假設(shè)你要根據(jù)在線翻譯 API 將英文文件名翻譯為中文再重命名 —— 這種需求用 Shell 實(shí)現(xiàn)非常困難,而 Java 可輕松集成 HTTP 客戶端。

場(chǎng)景七:智能重命名 —— 根據(jù) EXIF 信息重命名照片

如果你處理的是照片,可能希望根據(jù)拍攝時(shí)間重命名,如:

IMG_1234.jpg20230405_142030.jpg

這需要讀取 EXIF 數(shù)據(jù)。Shell 可借助 exiftool 實(shí)現(xiàn)。

安裝 exiftool:

sudo apt install libimage-exiftool-perl

Shell 腳本:

#!/bin/bash
# rename_by_exif.sh

for file in *.jpg *.jpeg *.JPG; do
    if [ -f "$file" ]; then
        datetime=$(exiftool -d "%Y%m%d_%H%M%S" -DateTimeOriginal -s3 "$file" 2>/dev/null)
        if [ -n "$datetime" ]; then
            new_name="${datetime}.jpg"
            mv "$file" "$new_name"
            echo "?? $file → $new_name"
        else
            echo "?? 未找到EXIF信息: $file"
        fi
    fi
done

Java 實(shí)現(xiàn)(需引入 metadata-extractor 庫(kù)):

由于標(biāo)準(zhǔn) Java 不支持讀取 EXIF,你需要添加依賴(如 Maven):

<dependency>
    <groupId>com.drewnoakes</groupId>
    <artifactId>metadata-extractor</artifactId>
    <version>2.18.0</version>
</dependency>

然后編寫(xiě)代碼:

import com.drew.imaging.ImageMetadataReader;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifSubIFDDirectory;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
public class RenameByExif {
    public static void main(String[] args) {
        File dir = new File(".");
        File[] imageFiles = dir.listFiles((d, name) ->
            name.toLowerCase().matches(".*\\.(jpg|jpeg)$")
        );
        if (imageFiles != null) {
            for (File file : imageFiles) {
                try {
                    Metadata metadata = ImageMetadataReader.readMetadata(file);
                    ExifSubIFDDirectory directory = metadata.getFirstDirectoryOfType(ExifSubIFDDirectory.class);
                    if (directory != null && directory.getDateOriginal() != null) {
                        Date date = directory.getDateOriginal();
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
                        String newName = sdf.format(date) + ".jpg";
                        File newFile = new File(file.getParent(), newName);
                        if (file.renameTo(newFile)) {
                            System.out.println("?? " + file.getName() + " → " + newName);
                        } else {
                            System.err.println("? 重命名失敗: " + file.getName());
                        }
                    } else {
                        System.out.println("?? 未找到拍攝時(shí)間: " + file.getName());
                    }
                } catch (Exception e) {
                    System.err.println("? 讀取EXIF失敗: " + file.getName() + " - " + e.getMessage());
                }
            }
        }
    }
}

應(yīng)用場(chǎng)景:攝影師整理素材、家庭相冊(cè)歸檔、監(jiān)控視頻按時(shí)間排序等。

場(chǎng)景八:撤銷重命名 —— 創(chuàng)建備份與恢復(fù)機(jī)制

批量操作最怕“手滑”。我們可以讓腳本自動(dòng)生成重命名映射表,便于回滾。

Shell 帶備份版本:

#!/bin/bash
# rename_with_backup.sh

BACKUP_FILE="rename_backup_$(date +%Y%m%d_%H%M%S).csv"

echo "原文件名,新文件名" > "$BACKUP_FILE"

for file in *.txt; do
    if [ -f "$file" ]; then
        new_name="${file%.txt}.md"
        if mv "$file" "$new_name" 2>/dev/null; then
            echo "$file,$new_name" >> "$BACKUP_FILE"
            echo "? $file → $new_name"
        else
            echo "? 失敗: $file"
        fi
    fi
done

echo "?? 備份記錄已保存至: $BACKUP_FILE"

恢復(fù)腳本:

#!/bin/bash
# restore_names.sh

if [ $# -eq 0 ]; then
    echo "用法: $0 <備份文件.csv>"
    exit 1
fi

backup_file="$1"

if [ ! -f "$backup_file" ]; then
    echo "? 備份文件不存在: $backup_file"
    exit 1
fi

# 跳過(guò)第一行(標(biāo)題)
tail -n +2 "$backup_file" | while IFS=',' read -r old_name new_name; do
    if [ -f "$new_name" ]; then
        if mv "$new_name" "$old_name" 2>/dev/null; then
            echo "??  已恢復(fù): $new_name → $old_name"
        else
            echo "? 恢復(fù)失敗: $new_name"
        fi
    else
        echo "??  文件不存在,跳過(guò): $new_name"
    fi
done

Java 也可實(shí)現(xiàn)類似功能,通過(guò)寫(xiě)入 CSV 或 JSON 記錄變更,這里不再贅述。

最佳實(shí)踐總結(jié)

  1. Always Backup First —— 操作前備份原文件或生成映射表
  2. Dry Run —— 先打印將要執(zhí)行的操作,確認(rèn)無(wú)誤后再真正執(zhí)行
  3. Use Quotes —— 文件名用雙引號(hào)包裹,防止空格導(dǎo)致解析錯(cuò)誤
  4. Check Existence —— 使用 -f 判斷文件是否存在
  5. Log Everything —— 記錄成功與失敗,便于審計(jì)
  6. Handle Encoding —— 注意文件名編碼問(wèn)題,尤其在中文環(huán)境下
  7. Test on Sample —— 先在測(cè)試目錄驗(yàn)證腳本邏輯

場(chǎng)景九:交互式重命名 —— 用戶確認(rèn)每一步

有時(shí)你希望每改一個(gè)文件都讓用戶確認(rèn)。

Shell 交互版本:

#!/bin/bash
# interactive_rename.sh

for file in *.txt; do
    if [ -f "$file" ]; then
        new_name="${file%.txt}.md"
        read -p "重命名 $file → $new_name ? (y/N): " confirm
        if [[ "$confirm" =~ ^[Yy]$ ]]; then
            mv "$file" "$new_name"
            echo "? 已重命名"
        else
            echo "??  跳過(guò)"
        fi
    fi
done

Java 交互版本:

import java.io.File;
import java.util.Scanner;
public class InteractiveRename {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        File dir = new File(".");
        File[] txtFiles = dir.listFiles((d, name) -> name.endsWith(".txt"));
        if (txtFiles != null) {
            for (File file : txtFiles) {
                String newName = file.getName().replace(".txt", ".md");
                System.out.print("重命名 " + file.getName() + " → " + newName + " ? (y/N): ");
                String input = scanner.nextLine();
                if ("y".equalsIgnoreCase(input) || "yes".equalsIgnoreCase(input)) {
                    File newFile = new File(file.getParent(), newName);
                    if (file.renameTo(newFile)) {
                        System.out.println("? 已重命名");
                    } else {
                        System.err.println("? 重命名失敗");
                    }
                } else {
                    System.out.println("??  跳過(guò)");
                }
            }
        }
        scanner.close();
    }
}

結(jié)語(yǔ):選擇合適的工具,事半功倍

Shell 腳本輕量、高效、貼近系統(tǒng),適合快速解決一次性或周期性文件處理任務(wù);Java 功能完整、跨平臺(tái)、易維護(hù),適合集成到大型應(yīng)用或需要復(fù)雜邏輯的場(chǎng)景。

掌握兩者,你就能在不同情境下游刃有余。無(wú)論是運(yùn)維人員、開(kāi)發(fā)者還是普通用戶,批量重命名都是提升效率的必備技能。

常見(jiàn)問(wèn)題 FAQ

Q:文件名含空格怎么辦?
A:始終用雙引號(hào)包裹變量,如 "$file",避免被 shell 分詞。

Q:如何處理隱藏文件(以點(diǎn)開(kāi)頭)?
A:使用 .* 匹配,但注意 ... 目錄,可用 [!.]*.[!.]*。

Q:rename 命令在 macOS 上行為不同?
A:是的,macOS 自帶的 rename 是 C 語(yǔ)言版本,功能弱。建議安裝 Perl 版:brew install rename。

Q:Java renameTo 有時(shí)失?。?/strong>
A:可能是權(quán)限問(wèn)題、目標(biāo)文件已存在、跨文件系統(tǒng)等。建議使用 java.nio.file.Files.move() 替代。

場(chǎng)景十:結(jié)合 Git —— 重命名后自動(dòng)提交

如果你在 Git 倉(cāng)庫(kù)中工作,重命名后可能希望自動(dòng)提交變更。

Shell + Git:

#!/bin/bash
# git_rename.sh

git add .

for file in *.txt; do
    if [ -f "$file" ]; then
        new_name="${file%.txt}.md"
        git mv "$file" "$new_name"
        echo "?? $file → $new_name"
    fi
done

git commit -m "批量重命名:txt → md"
echo "? 已提交到 Git"

Java 也可調(diào)用 Runtime.getRuntime().exec("git ..."),但不推薦,不如直接用 Shell。

無(wú)論你是 Linux 新手還是資深開(kāi)發(fā)者,掌握批量重命名技巧都能極大提升工作效率。希望本文的 Shell 與 Java 雙重視角能為你提供全面參考。動(dòng)手試試吧!

以上就是使用Shell腳本和Java實(shí)現(xiàn)批量修改文件名功能的詳細(xì)內(nèi)容,更多關(guān)于Shell Java批量修改文件名的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Python執(zhí)行Linux系統(tǒng)命令的4種方法

    Python執(zhí)行Linux系統(tǒng)命令的4種方法

    這篇文章主要介紹了Python執(zhí)行Linux系統(tǒng)命令的4種方法,即在Python腳本中調(diào)用Shell命令,需要的朋友可以參考下
    2014-10-10
  • 圖片批量壓縮大小腳本分享

    圖片批量壓縮大小腳本分享

    這篇文章主要介紹了圖片批量壓縮大小的腳本,需要的朋友可以參考下
    2014-04-04
  • Shell程序退出狀態(tài)碼的命令詳解

    Shell程序退出狀態(tài)碼的命令詳解

    在本篇文章當(dāng)中主要給大家介紹一個(gè)shell的小知識(shí)——狀態(tài)碼。這是當(dāng)我們的程序退出的時(shí)候,子進(jìn)程會(huì)將自己程序的退出碼傳遞給父進(jìn)程,有時(shí)候我們可以利用這一操作做一些進(jìn)程退出之后的事情,比如當(dāng)程序執(zhí)行失敗或者被某個(gè)信號(hào)殺死我們就可以了解到,然后做出對(duì)應(yīng)的措施
    2022-10-10
  • Shell中的函數(shù)、函數(shù)定義、作用域問(wèn)題介紹

    Shell中的函數(shù)、函數(shù)定義、作用域問(wèn)題介紹

    這篇文章主要介紹了Shell中的函數(shù)、函數(shù)定義、作用域問(wèn)題介紹,本文講解了Shell中函數(shù)的定義、自定義函數(shù)的例子、作用域問(wèn)題等內(nèi)容,需要的朋友可以參考下
    2014-11-11
  • CentOS下對(duì)shell腳本加密的二種方法

    CentOS下對(duì)shell腳本加密的二種方法

    這篇文章主要介紹了CentOS下對(duì)shell腳本加密的二種方法,本文介紹了gzexe、shc兩款加密工具,并分別講解了加密方法,需要的朋友可以參考下
    2014-12-12
  • linux 中open()函數(shù)詳解及簡(jiǎn)單實(shí)例

    linux 中open()函數(shù)詳解及簡(jiǎn)單實(shí)例

    這篇文章主要介紹了linux 中open()函數(shù)詳解及簡(jiǎn)單實(shí)例的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • 輕松掌握Linux關(guān)機(jī)重啟命令

    輕松掌握Linux關(guān)機(jī)重啟命令

    在Linux系統(tǒng)下關(guān)機(jī)重啟命令有:shutdown、halt、rebbot、init命令,對(duì)于這些命令來(lái)說(shuō),他們的內(nèi)部工作過(guò)程是不相同的,下面小編給大家分享一篇文章有助于輕松掌握l(shuí)inux關(guān)機(jī)重啟命令
    2015-11-11
  • Shell腳本讀取ini配置文件的實(shí)現(xiàn)代碼2例

    Shell腳本讀取ini配置文件的實(shí)現(xiàn)代碼2例

    這篇文章主要介紹了Shell腳本讀取ini配置文件的實(shí)現(xiàn)代碼2例,如果只是讀取內(nèi)容推薦使用簡(jiǎn)單版,有更多需求請(qǐng)見(jiàn)復(fù)雜版,需要的朋友可以參考下
    2014-08-08
  • touch shell腳本并修改為777權(quán)限的方法

    touch shell腳本并修改為777權(quán)限的方法

    這篇文章主要介紹了touch shell腳本并修改為777權(quán)限的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-06-06
  • shell實(shí)現(xiàn)四則運(yùn)算簡(jiǎn)單方法

    shell實(shí)現(xiàn)四則運(yùn)算簡(jiǎn)單方法

    在剛剛學(xué)習(xí)寫(xiě)shell 批處理時(shí)候,進(jìn)行邏輯運(yùn)算中,少不了需要進(jìn)行基礎(chǔ)的:四則運(yùn)算,這里說(shuō)說(shuō)在linux shell 里面簡(jiǎn)單的實(shí)現(xiàn)方法
    2014-03-03

最新評(píng)論

丹阳市| 济宁市| 竹山县| 云梦县| 贵州省| 若尔盖县| 论坛| 颍上县| 嘉鱼县| 新建县| 无棣县| 汉川市| 金山区| 屏东县| 色达县| 叶城县| 汨罗市| 昌邑市| 蒙阴县| 慈溪市| 繁峙县| 凤山市| 中江县| 壶关县| 奈曼旗| 广元市| 赤城县| 宜宾县| 大田县| 盱眙县| 阜新| 白水县| 富源县| 莱西市| 扎赉特旗| 疏附县| 芜湖县| 合阳县| 汉沽区| 泰兴市| 宁远县|