C# 完全学习指南C# 完全学习指南
首页
基础教程
进阶内容
实战项目
编程指南
首页
基础教程
进阶内容
实战项目
编程指南
  • 实战项目

    • 🎨 实战项目
    • 项目1 - 控制台计算器
    • 项目2 - 待办事项管理
    • 项目3 - 学生信息管理系统
    • 项目4 - 命令行文件管理器
    • 项目5 - Web API 接口开发

项目4 - 命令行文件管理器

嗨,朋友!我是长安。

完成了学生管理系统,这次我们要做一个更实用的项目 —— 命令行文件管理器!这个项目会让你学会文件和目录操作、命令解析和系统集成。通过这个项目,你将掌握如何与操作系统交互,处理文件和目录的各种操作。

🎯 项目目标

通过这个项目,你将:

  • 掌握文件和目录的基本操作
  • 学会解析和处理用户命令
  • 理解路径和文件系统的概念
  • 实现类似 Windows CMD 或 Linux Shell 的基本功能
  • 学会使用 System.IO 命名空间

📁 项目结构

FileManager/
├── Program.cs           # 主程序
├── FileItem.cs          # 文件/目录实体类  
├── FileManager.cs       # 文件管理核心类
└── CommandParser.cs     # 命令解析类

🎯 项目需求

功能列表

  1. ls (list) - 列出当前目录下的文件和文件夹
  2. cd (change directory) - 切换目录
  3. pwd (print working directory) - 显示当前目录
  4. mkdir - 创建新目录
  5. touch - 创建新文件
  6. rm (remove) - 删除文件或目录
  7. cp (copy) - 复制文件或目录
  8. mv (move) - 移动或重命名文件/目录
  9. cat - 查看文件内容
  10. find - 搜索文件
  11. tree - 以树形结构显示目录
  12. help - 显示帮助信息
  13. exit - 退出程序

运行效果

===== 命令行文件管理器 =====
当前目录: C:\Users\YourName\Documents

> ls

目录列表:
[DIR]  Projects
[DIR]  Photos
[FILE] readme.txt (1.2 KB)
[FILE] notes.md (3.5 KB)

> cd Projects
当前目录: C:\Users\YourName\Documents\Projects

> mkdir MyApp
✓ 已创建目录: MyApp

> tree
Projects/
├── MyApp/
├── OldProject/
│   ├── src/
│   └── README.md
└── README.md

🤔 需求分析

在开始编码之前,我们先分析一下需要做什么:

  1. 命令解析

    • 接收用户输入的命令字符串
    • 解析命令名和参数
    • 验证命令格式
  2. 文件操作

    • 列出目录内容
    • 创建、删除文件和目录
    • 复制和移动文件
    • 读取文件内容
  3. 路径管理

    • 维护当前工作目录
    • 处理相对路径和绝对路径
    • 路径验证
  4. 用户交互

    • 显示友好的提示符
    • 提供清晰的反馈信息
    • 错误提示和异常处理

📐 功能设计

1. 程序流程图

开始
  ↓
显示欢迎信息
设置初始工作目录
  ↓
┌─────────────────┐
│ 显示提示符      │←──────┐
│ 等待用户输入    │       │
└─────────────────┘       │
  ↓                       │
解析命令                   │
  ↓                       │
┌─────────────────┐       │
│ 命令分发        │       │
│ - ls            │───────┤
│ - cd            │───────┤
│ - mkdir         │───────┤
│ - rm            │───────┤
│ - cp/mv         │───────┤
│ - cat           │───────┤
│ - find/tree     │───────┤
│ - help          │───────┤
│ - exit          │       │
└─────────────────┘       │
  ↓                       │
执行命令                   │
  ↓                       │
显示结果 ─────────────────┘
  ↓
退出

2. 类设计

FileItem 类 - 文件/目录信息

属性:
- Name: string (名称)
- FullPath: string (完整路径)
- IsDirectory: bool (是否是目录)
- Size: long (文件大小)
- CreatedTime: DateTime (创建时间)
- ModifiedTime: DateTime (修改时间)

方法:
- GetFormattedSize() (格式化大小显示)
- GetIcon() (获取图标)

FileManager 类 - 文件管理核心

属性:
- CurrentDirectory: string (当前目录)

方法:
- ListDirectory() (列出目录)
- ChangeDirectory() (切换目录)
- CreateDirectory() (创建目录)
- CreateFile() (创建文件)
- DeleteItem() (删除项目)
- CopyItem() (复制项目)
- MoveItem() (移动项目)
- ReadFile() (读取文件)
- SearchFiles() (搜索文件)
- ShowTree() (显示目录树)

CommandParser 类 - 命令解析

方法:
- Parse() (解析命令)
- GetCommandName() (获取命令名)
- GetArguments() (获取参数)
- Validate() (验证命令)

💻 代码实现

第一步:项目初始化

# 创建新的控制台项目
mkdir FileManager
cd FileManager
dotnet new console

第二步:实现 FileItem 类

创建 FileItem.cs 文件:

using System;
using System.IO;

namespace FileManager
{
    /// <summary>
    /// 文件或目录项
    /// </summary>
    public class FileItem
    {
        public string Name { get; set; }
        public string FullPath { get; set; }
        public bool IsDirectory { get; set; }
        public long Size { get; set; }
        public DateTime CreatedTime { get; set; }
        public DateTime ModifiedTime { get; set; }
        
        /// <summary>
        /// 从文件系统信息创建 FileItem
        /// </summary>
        public static FileItem FromFileInfo(FileInfo fileInfo)
        {
            return new FileItem
            {
                Name = fileInfo.Name,
                FullPath = fileInfo.FullName,
                IsDirectory = false,
                Size = fileInfo.Length,
                CreatedTime = fileInfo.CreationTime,
                ModifiedTime = fileInfo.LastWriteTime
            };
        }
        
        /// <summary>
        /// 从目录信息创建 FileItem
        /// </summary>
        public static FileItem FromDirectoryInfo(DirectoryInfo dirInfo)
        {
            return new FileItem
            {
                Name = dirInfo.Name,
                FullPath = dirInfo.FullName,
                IsDirectory = true,
                Size = 0,
                CreatedTime = dirInfo.CreationTime,
                ModifiedTime = dirInfo.LastWriteTime
            };
        }
        
        /// <summary>
        /// 获取格式化的文件大小
        /// </summary>
        public string GetFormattedSize()
        {
            if (IsDirectory)
                return "<DIR>";
            
            string[] sizes = { "B", "KB", "MB", "GB", "TB" };
            double len = Size;
            int order = 0;
            
            while (len >= 1024 && order < sizes.Length - 1)
            {
                order++;
                len /= 1024;
            }
            
            return $"{len:0.##} {sizes[order]}";
        }
        
        /// <summary>
        /// 获取图标
        /// </summary>
        public string GetIcon()
        {
            return IsDirectory ? "📁" : "📄";
        }
        
        /// <summary>
        /// 获取类型标识
        /// </summary>
        public string GetTypeLabel()
        {
            return IsDirectory ? "[DIR] " : "[FILE]";
        }
    }
}

代码讲解:

  • 使用 FileInfo 和 DirectoryInfo 获取文件系统信息
  • GetFormattedSize() 方法将字节转换为易读的单位(KB, MB等)
  • 提供静态工厂方法从系统信息创建对象
  • 使用 emoji 图标使输出更友好

第三步:实现 CommandParser 类

创建 CommandParser.cs 文件:

using System;
using System.Collections.Generic;
using System.Linq;

namespace FileManager
{
    /// <summary>
    /// 命令解析器
    /// </summary>
    public class CommandParser
    {
        public string CommandName { get; private set; }
        public List<string> Arguments { get; private set; }
        
        /// <summary>
        /// 解析命令字符串
        /// </summary>
        public bool Parse(string input)
        {
            if (string.IsNullOrWhiteSpace(input))
            {
                return false;
            }
            
            // 分割命令和参数
            var parts = input.Trim().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            
            if (parts.Length == 0)
            {
                return false;
            }
            
            CommandName = parts[0].ToLower();
            Arguments = parts.Skip(1).ToList();
            
            return true;
        }
        
        /// <summary>
        /// 获取指定索引的参数
        /// </summary>
        public string GetArgument(int index, string defaultValue = "")
        {
            if (index < 0 || index >= Arguments.Count)
            {
                return defaultValue;
            }
            return Arguments[index];
        }
        
        /// <summary>
        /// 检查是否有指定数量的参数
        /// </summary>
        public bool HasArguments(int count)
        {
            return Arguments.Count >= count;
        }
    }
}

代码讲解:

  • 使用 Split 方法分割命令字符串
  • Skip(1) 跳过命令名,获取参数列表
  • 提供安全的参数获取方法,避免索引越界

第四步:实现 FileManagerCore 类

创建 FileManagerCore.cs 文件(这是核心功能类):

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace FileManager
{
    /// <summary>
    /// 文件管理核心类
    /// </summary>
    public class FileManagerCore
    {
        private string currentDirectory;
        
        public string CurrentDirectory 
        { 
            get => currentDirectory;
            private set => currentDirectory = value;
        }
        
        public FileManagerCore()
        {
            // 初始化为用户文档目录
            CurrentDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
        }
        
        /// <summary>
        /// 列出目录内容
        /// </summary>
        public void ListDirectory(string path = null)
        {
            try
            {
                string targetPath = path ?? CurrentDirectory;
                var dirInfo = new DirectoryInfo(targetPath);
                
                if (!dirInfo.Exists)
                {
                    Console.WriteLine("✗ 目录不存在!");
                    return;
                }
                
                Console.WriteLine($"\n目录: {dirInfo.FullName}");
                Console.WriteLine(new string('-', 60));
                
                // 列出子目录
                var directories = dirInfo.GetDirectories()
                    .OrderBy(d => d.Name)
                    .ToList();
                    
                // 列出文件
                var files = dirInfo.GetFiles()
                    .OrderBy(f => f.Name)
                    .ToList();
                
                if (directories.Count == 0 && files.Count == 0)
                {
                    Console.WriteLine("(空目录)");
                    return;
                }
                
                // 显示目录
                foreach (var dir in directories)
                {
                    var item = FileItem.FromDirectoryInfo(dir);
                    Console.WriteLine($"{item.GetIcon()} {item.GetTypeLabel()}{item.Name}");
                }
                
                // 显示文件
                foreach (var file in files)
                {
                    var item = FileItem.FromFileInfo(file);
                    Console.WriteLine($"{item.GetIcon()} {item.GetTypeLabel()}{item.Name,-40} {item.GetFormattedSize(),10}");
                }
                
                Console.WriteLine(new string('-', 60));
                Console.WriteLine($"共 {directories.Count} 个目录, {files.Count} 个文件");
            }
            catch (UnauthorizedAccessException)
            {
                Console.WriteLine("✗ 没有访问权限!");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"✗ 错误: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 切换目录
        /// </summary>
        public void ChangeDirectory(string path)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(path))
                {
                    Console.WriteLine("✗ 请指定目录路径!");
                    return;
                }
                
                // 处理特殊路径
                if (path == "..")
                {
                    var parent = Directory.GetParent(CurrentDirectory);
                    if (parent != null)
                    {
                        CurrentDirectory = parent.FullName;
                        Console.WriteLine($"✓ 当前目录: {CurrentDirectory}");
                    }
                    else
                    {
                        Console.WriteLine("✗ 已经在根目录!");
                    }
                    return;
                }
                
                if (path == "~")
                {
                    CurrentDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
                    Console.WriteLine($"✓ 当前目录: {CurrentDirectory}");
                    return;
                }
                
                // 处理绝对路径和相对路径
                string targetPath = Path.IsPathRooted(path) 
                    ? path 
                    : Path.Combine(CurrentDirectory, path);
                
                if (Directory.Exists(targetPath))
                {
                    CurrentDirectory = Path.GetFullPath(targetPath);
                    Console.WriteLine($"✓ 当前目录: {CurrentDirectory}");
                }
                else
                {
                    Console.WriteLine("✗ 目录不存在!");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"✗ 错误: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 显示当前目录
        /// </summary>
        public void PrintWorkingDirectory()
        {
            Console.WriteLine(CurrentDirectory);
        }
        
        /// <summary>
        /// 创建目录
        /// </summary>
        public void CreateDirectory(string dirName)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(dirName))
                {
                    Console.WriteLine("✗ 请指定目录名!");
                    return;
                }
                
                string targetPath = Path.Combine(CurrentDirectory, dirName);
                
                if (Directory.Exists(targetPath))
                {
                    Console.WriteLine("✗ 目录已存在!");
                    return;
                }
                
                Directory.CreateDirectory(targetPath);
                Console.WriteLine($"✓ 已创建目录: {dirName}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"✗ 创建失败: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 创建文件
        /// </summary>
        public void CreateFile(string fileName)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(fileName))
                {
                    Console.WriteLine("✗ 请指定文件名!");
                    return;
                }
                
                string targetPath = Path.Combine(CurrentDirectory, fileName);
                
                if (File.Exists(targetPath))
                {
                    Console.WriteLine("✗ 文件已存在!");
                    return;
                }
                
                File.Create(targetPath).Dispose();
                Console.WriteLine($"✓ 已创建文件: {fileName}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"✗ 创建失败: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 删除文件或目录
        /// </summary>
        public void Remove(string name, bool recursive = false)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(name))
                {
                    Console.WriteLine("✗ 请指定要删除的文件或目录!");
                    return;
                }
                
                string targetPath = Path.Combine(CurrentDirectory, name);
                
                if (Directory.Exists(targetPath))
                {
                    if (!recursive)
                    {
                        var dirInfo = new DirectoryInfo(targetPath);
                        if (dirInfo.GetFiles().Length > 0 || dirInfo.GetDirectories().Length > 0)
                        {
                            Console.WriteLine("✗ 目录不为空! 使用 'rm -r <目录名>' 删除非空目录");
                            return;
                        }
                    }
                    Directory.Delete(targetPath, recursive);
                    Console.WriteLine($"✓ 已删除目录: {name}");
                }
                else if (File.Exists(targetPath))
                {
                    File.Delete(targetPath);
                    Console.WriteLine($"✓ 已删除文件: {name}");
                }
                else
                {
                    Console.WriteLine("✗ 文件或目录不存在!");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"✗ 删除失败: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 复制文件或目录
        /// </summary>
        public void Copy(string source, string destination)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(source) || string.IsNullOrWhiteSpace(destination))
                {
                    Console.WriteLine("✗ 请指定源和目标路径!");
                    return;
                }
                
                string sourcePath = Path.Combine(CurrentDirectory, source);
                string destPath = Path.Combine(CurrentDirectory, destination);
                
                if (File.Exists(sourcePath))
                {
                    File.Copy(sourcePath, destPath, true);
                    Console.WriteLine($"✓ 已复制文件: {source} -> {destination}");
                }
                else if (Directory.Exists(sourcePath))
                {
                    CopyDirectory(sourcePath, destPath);
                    Console.WriteLine($"✓ 已复制目录: {source} -> {destination}");
                }
                else
                {
                    Console.WriteLine("✗ 源文件或目录不存在!");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"✗ 复制失败: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 递归复制目录
        /// </summary>
        private void CopyDirectory(string sourceDir, string destDir)
        {
            Directory.CreateDirectory(destDir);
            
            foreach (string file in Directory.GetFiles(sourceDir))
            {
                string destFile = Path.Combine(destDir, Path.GetFileName(file));
                File.Copy(file, destFile, true);
            }
            
            foreach (string dir in Directory.GetDirectories(sourceDir))
            {
                string destSubDir = Path.Combine(destDir, Path.GetFileName(dir));
                CopyDirectory(dir, destSubDir);
            }
        }
        
        /// <summary>
        /// 移动或重命名
        /// </summary>
        public void Move(string source, string destination)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(source) || string.IsNullOrWhiteSpace(destination))
                {
                    Console.WriteLine("✗ 请指定源和目标路径!");
                    return;
                }
                
                string sourcePath = Path.Combine(CurrentDirectory, source);
                string destPath = Path.Combine(CurrentDirectory, destination);
                
                if (File.Exists(sourcePath))
                {
                    File.Move(sourcePath, destPath);
                    Console.WriteLine($"✓ 已移动文件: {source} -> {destination}");
                }
                else if (Directory.Exists(sourcePath))
                {
                    Directory.Move(sourcePath, destPath);
                    Console.WriteLine($"✓ 已移动目录: {source} -> {destination}");
                }
                else
                {
                    Console.WriteLine("✗ 源文件或目录不存在!");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"✗ 移动失败: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 查看文件内容
        /// </summary>
        public void ViewFile(string fileName)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(fileName))
                {
                    Console.WriteLine("✗ 请指定文件名!");
                    return;
                }
                
                string filePath = Path.Combine(CurrentDirectory, fileName);
                
                if (!File.Exists(filePath))
                {
                    Console.WriteLine("✗ 文件不存在!");
                    return;
                }
                
                // 检查文件大小
                var fileInfo = new FileInfo(filePath);
                if (fileInfo.Length > 1024 * 1024) // 大于 1MB
                {
                    Console.Write("文件较大, 确认查看? (y/n): ");
                    if (Console.ReadLine()?.ToLower() != "y")
                    {
                        return;
                    }
                }
                
                Console.WriteLine($"\n--- {fileName} ---");
                string content = File.ReadAllText(filePath);
                Console.WriteLine(content);
                Console.WriteLine("--- End ---\n");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"✗ 读取失败: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 搜索文件
        /// </summary>
        public void Search(string pattern)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(pattern))
                {
                    Console.WriteLine("✗ 请指定搜索模式!");
                    return;
                }
                
                Console.WriteLine($"\n搜索 '{pattern}' ...");
                
                var files = Directory.GetFiles(CurrentDirectory, $"*{pattern}*", SearchOption.AllDirectories);
                var dirs = Directory.GetDirectories(CurrentDirectory, $"*{pattern}*", SearchOption.AllDirectories);
                
                if (dirs.Length == 0 && files.Length == 0)
                {
                    Console.WriteLine("未找到匹配项");
                    return;
                }
                
                Console.WriteLine($"\n找到 {dirs.Length + files.Length} 个结果:\n");
                
                foreach (var dir in dirs)
                {
                    Console.WriteLine($"📁 [DIR]  {dir}");
                }
                
                foreach (var file in files)
                {
                    var fileInfo = new FileInfo(file);
                    Console.WriteLine($"📄 [FILE] {file} ({FormatBytes(fileInfo.Length)})");
                }
            }
            catch (UnauthorizedAccessException)
            {
                Console.WriteLine("✗ 某些目录没有访问权限");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"✗ 搜索失败: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 显示目录树
        /// </summary>
        public void ShowTree(string path = null, int maxDepth = 3)
        {
            try
            {
                string targetPath = path ?? CurrentDirectory;
                var dirInfo = new DirectoryInfo(targetPath);
                
                if (!dirInfo.Exists)
                {
                    Console.WriteLine("✗ 目录不存在!");
                    return;
                }
                
                Console.WriteLine($"\n{dirInfo.Name}/");
                ShowTreeRecursive(dirInfo, "", maxDepth, 0);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"✗ 错误: {ex.Message}");
            }
        }
        
        private void ShowTreeRecursive(DirectoryInfo directory, string indent, int maxDepth, int currentDepth)
        {
            if (currentDepth >= maxDepth)
            {
                return;
            }
            
            try
            {
                var items = directory.GetFileSystemInfos()
                    .OrderBy(i => i is FileInfo)
                    .ThenBy(i => i.Name)
                    .ToList();
                
                for (int i = 0; i < items.Count; i++)
                {
                    bool isLast = i == items.Count - 1;
                    string connector = isLast ? "└── " : "├── ";
                    string newIndent = isLast ? "    " : "│   ";
                    
                    if (items[i] is DirectoryInfo subDir)
                    {
                        Console.WriteLine($"{indent}{connector}📁 {subDir.Name}/");
                        ShowTreeRecursive(subDir, indent + newIndent, maxDepth, currentDepth + 1);
                    }
                    else if (items[i] is FileInfo file)
                    {
                        Console.WriteLine($"{indent}{connector}📄 {file.Name}");
                    }
                }
            }
            catch (UnauthorizedAccessException)
            {
                Console.WriteLine($"{indent}✗ 无权访问");
            }
        }
        
        /// <summary>
        /// 格式化字节数
        /// </summary>
        private string FormatBytes(long bytes)
        {
            string[] sizes = { "B", "KB", "MB", "GB" };
            double len = bytes;
            int order = 0;
            
            while (len >= 1024 && order < sizes.Length - 1)
            {
                order++;
                len /= 1024;
            }
            
            return $"{len:0.##} {sizes[order]}";
        }
    }
}

代码讲解:

  • Path.Combine - 正确组合路径,自动处理分隔符
  • Path.IsPathRooted - 判断是否为绝对路径
  • Directory.GetParent - 获取父目录
  • SearchOption.AllDirectories - 递归搜索所有子目录
  • 特殊路径处理: ..(父目录), ~(用户目录)
  • 递归方法实现目录复制和树形显示

第五步:实现主程序

修改 Program.cs 文件:

using System;

namespace FileManager
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("===== 命令行文件管理器 =====");
            Console.WriteLine("输入 'help' 查看帮助信息\n");
            
            var fileManager = new FileManagerCore();
            var parser = new CommandParser();
            
            bool running = true;
            
            while (running)
            {
                // 显示提示符
                Console.ForegroundColor = ConsoleColor.Green;
                Console.Write($"\n{fileManager.CurrentDirectory}\n> ");
                Console.ResetColor();
                
                // 读取用户输入
                string input = Console.ReadLine();
                
                // 解析命令
                if (!parser.Parse(input))
                {
                    continue;
                }
                
                Console.WriteLine();
                
                // 执行命令
                try
                {
                    switch (parser.CommandName)
                    {
                        case "ls":
                        case "dir":
                            fileManager.ListDirectory();
                            break;
                        
                        case "cd":
                            string path = parser.GetArgument(0);
                            fileManager.ChangeDirectory(path);
                            break;
                        
                        case "pwd":
                            fileManager.PrintWorkingDirectory();
                            break;
                        
                        case "mkdir":
                            string dirName = parser.GetArgument(0);
                            fileManager.CreateDirectory(dirName);
                            break;
                        
                        case "touch":
                            string fileName = parser.GetArgument(0);
                            fileManager.CreateFile(fileName);
                            break;
                        
                        case "rm":
                        case "del":
                            bool recursive = parser.GetArgument(0) == "-r";
                            string targetName = recursive ? parser.GetArgument(1) : parser.GetArgument(0);
                            fileManager.Remove(targetName, recursive);
                            break;
                        
                        case "cp":
                        case "copy":
                            if (!parser.HasArguments(2))
                            {
                                Console.WriteLine("✗ 用法: cp <源> <目标>");
                                break;
                            }
                            fileManager.Copy(parser.GetArgument(0), parser.GetArgument(1));
                            break;
                        
                        case "mv":
                        case "move":
                            if (!parser.HasArguments(2))
                            {
                                Console.WriteLine("✗ 用法: mv <源> <目标>");
                                break;
                            }
                            fileManager.Move(parser.GetArgument(0), parser.GetArgument(1));
                            break;
                        
                        case "cat":
                        case "type":
                            string viewFileName = parser.GetArgument(0);
                            fileManager.ViewFile(viewFileName);
                            break;
                        
                        case "find":
                        case "search":
                            string searchPattern = parser.GetArgument(0);
                            fileManager.Search(searchPattern);
                            break;
                        
                        case "tree":
                            fileManager.ShowTree();
                            break;
                        
                        case "help":
                        case "?":
                            ShowHelp();
                            break;
                        
                        case "clear":
                        case "cls":
                            Console.Clear();
                            break;
                        
                        case "exit":
                        case "quit":
                            running = false;
                            Console.WriteLine("再见!");
                            break;
                        
                        default:
                            Console.WriteLine($"✗ 未知命令: {parser.CommandName}");
                            Console.WriteLine("输入 'help' 查看可用命令");
                            break;
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"\n✗ 执行出错: {ex.Message}");
                }
            }
        }
        
        /// <summary>
        /// 显示帮助信息
        /// </summary>
        static void ShowHelp()
        {
            Console.WriteLine("===== 可用命令 =====");
            Console.WriteLine();
            Console.WriteLine("文件和目录操作:");
            Console.WriteLine("  ls, dir              列出当前目录内容");
            Console.WriteLine("  cd <目录>            切换目录 (.. 表示上级目录, ~ 表示用户目录)");
            Console.WriteLine("  pwd                  显示当前目录路径");
            Console.WriteLine("  mkdir <目录名>       创建新目录");
            Console.WriteLine("  touch <文件名>       创建新文件");
            Console.WriteLine("  rm <名称>            删除文件或空目录");
            Console.WriteLine("  rm -r <目录>         递归删除目录");
            Console.WriteLine("  cp <源> <目标>       复制文件或目录");
            Console.WriteLine("  mv <源> <目标>       移动或重命名");
            Console.WriteLine();
            Console.WriteLine("查看和搜索:");
            Console.WriteLine("  cat <文件名>         查看文件内容");
            Console.WriteLine("  find <关键词>        搜索文件");
            Console.WriteLine("  tree                 显示目录树");
            Console.WriteLine();
            Console.WriteLine("系统命令:");
            Console.WriteLine("  help, ?              显示此帮助信息");
            Console.WriteLine("  clear, cls           清屏");
            Console.WriteLine("  exit, quit           退出程序");
            Console.WriteLine();
            Console.WriteLine("示例:");
            Console.WriteLine("  cd Projects          进入 Projects 目录");
            Console.WriteLine("  mkdir MyFolder       创建名为 MyFolder 的目录");
            Console.WriteLine("  cp file.txt backup.txt  复制文件");
            Console.WriteLine("  find .cs             搜索所有 .cs 文件");
            Console.WriteLine("===================");
        }
    }
}

代码讲解:

  • 使用不同颜色的提示符增强用户体验
  • 支持命令别名(如 ls/dir, rm/del)
  • 统一的异常处理
  • 清晰的帮助文档

🎮 运行演示

1. 列出目录

C:\Users\YourName\Documents
> ls

目录: C:\Users\YourName\Documents
------------------------------------------------------------
📁 [DIR] Projects
📁 [DIR] Photos
📄 [FILE]readme.txt                             1.24 KB
📄 [FILE]notes.md                                3.56 KB
------------------------------------------------------------
共 2 个目录, 2 个文件

2. 创建和操作

C:\Users\YourName\Documents
> mkdir TestFolder
✓ 已创建目录: TestFolder

C:\Users\YourName\Documents
> cd TestFolder
✓ 当前目录: C:\Users\YourName\Documents\TestFolder

C:\Users\YourName\Documents\TestFolder
> touch hello.txt
✓ 已创建文件: hello.txt

C:\Users\YourName\Documents\TestFolder
> ls

目录: C:\Users\YourName\Documents\TestFolder
------------------------------------------------------------
📄 [FILE]hello.txt                               0 B
------------------------------------------------------------
共 0 个目录, 1 个文件

3. 搜索文件

C:\Users\YourName\Documents
> find .txt

搜索 '.txt' ...

找到 3 个结果:

📄 [FILE] C:\Users\YourName\Documents\readme.txt (1.24 KB)
📄 [FILE] C:\Users\YourName\Documents\TestFolder\hello.txt (0 B)
📄 [FILE] C:\Users\YourName\Documents\Projects\notes.txt (856 B)

4. 显示目录树

C:\Users\YourName\Documents
> tree

Documents/
├── 📁 Photos/
│   ├── 📄 photo1.jpg
│   └── 📄 photo2.jpg
├── 📁 Projects/
│   ├── 📁 MyApp/
│   │   ├── 📄 Program.cs
│   │   └── 📄 README.md
│   └── 📄 notes.txt
├── 📁 TestFolder/
│   └── 📄 hello.txt
├── 📄 notes.md
└── 📄 readme.txt

📚 知识点总结

这个项目用到了以下知识点:

知识点说明在项目中的应用
System.IO文件和目录操作File、Directory、FileInfo、DirectoryInfo
Path 类路径处理Path.Combine、Path.GetFullPath
异常处理处理文件操作异常UnauthorizedAccessException
递归算法遍历目录树ShowTreeRecursive、CopyDirectory
字符串处理命令解析Split、Trim、ToLower
LINQ数据查询排序OrderBy、Skip、ToList
格式化输出美化显示对齐、颜色、图标
枚举类型搜索选项SearchOption.AllDirectories

💡 代码优化建议

1. 添加命令历史

private static List<string> commandHistory = new List<string>();
private static int historyIndex = -1;

// 使用上下箭头键浏览历史命令
ConsoleKeyInfo key = Console.ReadKey();
if (key.Key == ConsoleKey.UpArrow)
{
    // 显示上一条命令
}

2. 支持通配符

public void ListDirectory(string pattern = "*")
{
    var files = Directory.GetFiles(CurrentDirectory, pattern);
    // 显示匹配的文件
}

3. 添加权限检查

private bool HasPermission(string path, FileSystemRights right)
{
    // 检查当前用户是否有指定权限
    return true;
}

4. 支持批量操作

public void RemoveMultiple(string[] patterns)
{
    foreach (var pattern in patterns)
    {
        var matches = Directory.GetFiles(CurrentDirectory, pattern);
        foreach (var file in matches)
        {
            File.Delete(file);
        }
    }
}

🚀 扩展功能建议

完成基本功能后,可以尝试添加:

  1. 文件压缩

    • 压缩文件和目录
    • 解压 ZIP 文件
    • 使用 System.IO.Compression
  2. 文件属性管理

    • 查看详细属性
    • 修改文件权限
    • 设置隐藏/只读属性
  3. 批处理脚本

    • 支持从文件读取命令
    • 执行批处理脚本
    • 条件判断和循环
  4. 文件比较

    • 比较两个文件内容
    • 显示差异
    • Diff 功能
  5. 快捷操作

    • 书签功能(保存常用目录)
    • 快速跳转
    • 别名设置
  6. 高级搜索

    • 按大小搜索
    • 按日期搜索
    • 正则表达式搜索

🎯 练习任务

  1. 基础任务:完整实现上述代码,确保所有命令正常工作

  2. 进阶任务:添加 rename 命令,专门用于重命名文件

  3. 挑战任务:实现文件压缩功能,支持创建和解压 ZIP 文件

  4. 超级挑战:实现书签功能,可以保存和快速跳转到常用目录

参考实现:书签功能

private Dictionary<string, string> bookmarks = new Dictionary<string, string>();

// 添加书签
public void AddBookmark(string name, string path = null)
{
    string targetPath = path ?? CurrentDirectory;
    bookmarks[name] = targetPath;
    Console.WriteLine($"✓ 已添加书签: {name} -> {targetPath}");
    SaveBookmarks();
}

// 跳转到书签
public void GotoBookmark(string name)
{
    if (bookmarks.ContainsKey(name))
    {
        ChangeDirectory(bookmarks[name]);
    }
    else
    {
        Console.WriteLine($"✗ 书签不存在: {name}");
    }
}

// 列出所有书签
public void ListBookmarks()
{
    Console.WriteLine("\n===== 书签列表 =====");
    foreach (var bookmark in bookmarks)
    {
        Console.WriteLine($"  {bookmark.Key,-15} -> {bookmark.Value}");
    }
    Console.WriteLine("===================");
}

// 在主程序中添加命令
case "bookmark":
    string bmName = parser.GetArgument(0);
    fileManager.AddBookmark(bmName);
    break;

case "goto":
    string bmTarget = parser.GetArgument(0);
    fileManager.GotoBookmark(bmTarget);
    break;

case "bookmarks":
    fileManager.ListBookmarks();
    break;

📝 项目小结

恭喜你完成了第四个项目!通过这个项目,你应该:

  • ✅ 掌握了文件和目录的各种操作
  • ✅ 学会了使用 System.IO 命名空间
  • ✅ 理解了路径处理和异常处理
  • ✅ 实现了递归算法
  • ✅ 学会了命令解析和用户交互
  • ✅ 体验了创建实用工具的完整过程

🎯 下一步

完成文件管理器项目后,下一个项目我们要做一个 "Web API 接口开发",学习如何创建 RESTful API,为前端或移动端提供数据服务!

最后一个项目:Web API →

💪 自我检测

  • [ ] 能够独立操作文件和目录
  • [ ] 理解绝对路径和相对路径的区别
  • [ ] 会处理文件操作的各种异常
  • [ ] 掌握递归算法的实现
  • [ ] 能够解析和处理用户命令
  • [ ] 理解如何与操作系统交互

第四个项目完成了!你已经能够开发实用的系统工具了!最后一个项目,加油!💪

最近更新: 2025/12/27 14:02
Contributors: 王长安
Prev
项目3 - 学生信息管理系统
Next
项目5 - Web API 接口开发