CodeGym /課程 /C# SELF /檔案與目錄的移動

檔案與目錄的移動

C# SELF
等級 40 , 課堂 3
開放

1. 介紹

需要做移動操作的情境很多:把「下載」的檔案從暫存資料夾搬到文件資料夾、批量整理照片、用範本改名、整理郵件與日誌。檔案系統喜歡有秩序──或者至少看起來有秩序!一個好的開發者應該會去維護這種秩序。

另外這類題目常出現在面試裡:「寫個工具,把所有檔案改名並加上版本號」,或是「做個命令,把過期文件移到 archive」。我們來看看在 C# 裡怎麼做。

功能概覽

在 .NET 裡有兩種主要方式做移動或改名:用靜態方法(File.Move, Directory.Move)或用實例方法(FileInfo.MoveTo, DirectoryInfo.MoveTo)。這些方法底層做的事情幾乎一樣,主要差別在語法風格。

.NET 怎麼「看」移動與改名?

注意!「改名」和「移動」本質上是同一個操作:一個檔案或資料夾由路徑來識別。如果路徑改了,就算是物件被「移動」或被「改名」。如果你只改名字但留在同一個資料夾──那是改名;如果整個路徑都變了──那是移動。哲學一點地說,有點像薛丁格的箱子:如果你給出一個新的路徑而且同時換了名字,那它就是既被移動又被改名!

2. 檔案移動與改名:範例

我們從簡單開始,基於一個小型的檔案管理器往下講。

靜態方法 File.Move

範例:如何移動(或改名)檔案:


// 將檔案 test1.txt 移到另一個資料夾並改名
File.Move(@"C:\Temp\test1.txt", @"C:\Archive\test1_archived.txt");

如果只是想在同一個資料夾改名字:


// 只是把檔案重新命名而已
File.Move(@"C:\Temp\test1.txt", @"C:\Temp\test_renamed.txt");

就這麼簡單!.NET 會把一個路徑「解綁」然後綁到另一個路徑,前提是兩個路徑都可用而且沒有衝突。

靜態方法 Directory.Move

對資料夾來說也類似:


// 移動資料夾
Directory.Move(@"C:\Temp\OldFolder", @"C:\Temp\NewFolder");

可以在同一層改名(只換名字)或把整個資料夾搬到別的地方。

3. 實例方法: FileInfo.MoveToDirectoryInfo.MoveTo

當你已經有一個 FileInfoDirectoryInfo 物件時,可以呼叫 MoveTo()


var fileInfo = new FileInfo(@"C:\Temp\test1.txt");
fileInfo.MoveTo(@"C:\Archive\test1_archived.txt");

// 資料夾:
var dirInfo = new DirectoryInfo(@"C:\Temp\OldFolder");
dirInfo.MoveTo(@"C:\Temp\NewFolder");

一樣的規則:如果新路徑是在同一個目錄但換了名字,那是改名;如果是不同目錄,那是移動。

4. 如果目標已經有檔案怎麼辦?

這就是會在最不方便的時候出問題的細節。

File.Move

如果目標路徑已經有檔案,會拋出 IOException,你的程式會丟錯:


try
{
    File.Move("data.txt", "archive\\data.txt");
}
catch (IOException ex)
{
    Console.WriteLine("目標檔案已存在! " + ex.Message);
}

FileInfo.MoveTo

情況一樣:如果目標檔案已存在,也會拋出 IOException

Directory.Move

資料夾的情況更嚴格:如果目標資料夾已經存在,會拋出例外。不能把資料夾移到一個已被占用的目標位置。

重點:在寫入目標前,務必檢查那裡有沒有同名的檔案或資料夾!


// 先冷靜檢查目標路徑有沒有檔案
if (!File.Exists("archive\\data.txt"))
{
    File.Move("data.txt", "archive\\data.txt");
}
else
{
    Console.WriteLine("目標檔案已存在!");
}

5. 有用的小提示

資料夾改名範例


var oldDir = @"C:\Projects\OldReport";
var newDir = @"C:\Projects\NewReport";

// 檢查新資料夾不存在且舊資料夾存在
if (Directory.Exists(oldDir) && !Directory.Exists(newDir))
{
    Directory.Move(oldDir, newDir);
    Console.WriteLine("資料夾已成功改名。");
}
else
{
    Console.WriteLine("錯誤:來源資料夾不存在或目標已存在。");
}

包含內部內容的改名

資料夾的所有內容(子資料夾、檔案)會隨著一起移動,不需要額外指令!很方便:一個命令就能把有任意深度結構的資料夾搬走。

最佳實務與 Path 類的實用方法

在改名或移動檔案時,使用 System.IO.Path 的方法來正確組路徑或改檔名是很重要的:

  • 取得不含副檔名的檔名: Path.GetFileNameWithoutExtension(path)
  • 只改副檔名: Path.ChangeExtension(path, ".bak")
  • 用不同名稱組成新路徑: Path.Combine(Path.GetDirectoryName(path), "newname.txt")

string oldPath = @"C:\Reports\2023_Final.docx";
string newName = "2023_Archive.docx";
string newPath = Path.Combine(Path.GetDirectoryName(oldPath)!, newName);

File.Move(oldPath, newPath);

6. 重要細節與常見錯誤

權限與鎖定

如果你沒有某個路徑的寫入權限,會拋出 UnauthorizedAccessException。類似地,如果檔案被其他程序鎖住(例如在 Word 裡開著),也會出錯。這是很常見的狀況。

跨不同磁碟或卷的移動

基本上 File.Move 在同一個卷/磁碟內會做「快速改名」操作。若你把檔案從 C 磁碟移到 D 磁碟,.NET 會自動做複製再刪除原檔的流程。如果目標磁碟空間不足或中途失敗,原始檔案會保留在原位。

有趣的事實:幾乎所有現代檔案系統在同一個卷內支援快速改名/移動,而跨卷就是複製 + 刪除的策略。

移動整個資料夾(Directory.Move

不能把資料夾移到它自己的子資料夾裡(例如把 C:\Data 移到 C:\Data\Archive)──這會出錯。

怎麼安全地移動?

在任何移動操作之前,特別是批量處理,先檢查來源是否存在(File.Exists, Directory.Exists)以及目標是否會衝突。別忘了用 try-catch:檔案系統很任性,可能在最意想不到的時候丟錯誤。

2
任務
C# SELF, 等級 40, 課堂 3
上鎖
將所有檔案從一個資料夾移動到另一個資料夾
將所有檔案從一個資料夾移動到另一個資料夾
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION