项目4 - 命令行文件管理器
嗨,朋友!我是长安。
完成了学生管理系统,这次我们要做一个更实用的项目 —— 命令行文件管理器!这个项目会让你学会文件和目录操作、命令解析和系统集成。通过这个项目,你将掌握如何与操作系统交互,处理文件和目录的各种操作。
🎯 项目目标
通过这个项目,你将:
- 掌握文件和目录的基本操作
- 学会解析和处理用户命令
- 理解路径和文件系统的概念
- 实现类似 Windows CMD 或 Linux Shell 的基本功能
- 学会使用
System.IO命名空间
📁 项目结构
FileManager/
├── Program.cs # 主程序
├── FileItem.cs # 文件/目录实体类
├── FileManager.cs # 文件管理核心类
└── CommandParser.cs # 命令解析类
🎯 项目需求
功能列表
- ls (list) - 列出当前目录下的文件和文件夹
- cd (change directory) - 切换目录
- pwd (print working directory) - 显示当前目录
- mkdir - 创建新目录
- touch - 创建新文件
- rm (remove) - 删除文件或目录
- cp (copy) - 复制文件或目录
- mv (move) - 移动或重命名文件/目录
- cat - 查看文件内容
- find - 搜索文件
- tree - 以树形结构显示目录
- help - 显示帮助信息
- 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. 程序流程图
开始
↓
显示欢迎信息
设置初始工作目录
↓
┌─────────────────┐
│ 显示提示符 │←──────┐
│ 等待用户输入 │ │
└─────────────────┘ │
↓ │
解析命令 │
↓ │
┌─────────────────┐ │
│ 命令分发 │ │
│ - 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);
}
}
}
🚀 扩展功能建议
完成基本功能后,可以尝试添加:
文件压缩
- 压缩文件和目录
- 解压 ZIP 文件
- 使用
System.IO.Compression
文件属性管理
- 查看详细属性
- 修改文件权限
- 设置隐藏/只读属性
批处理脚本
- 支持从文件读取命令
- 执行批处理脚本
- 条件判断和循环
文件比较
- 比较两个文件内容
- 显示差异
- Diff 功能
快捷操作
- 书签功能(保存常用目录)
- 快速跳转
- 别名设置
高级搜索
- 按大小搜索
- 按日期搜索
- 正则表达式搜索
🎯 练习任务
基础任务:完整实现上述代码,确保所有命令正常工作
进阶任务:添加
rename命令,专门用于重命名文件挑战任务:实现文件压缩功能,支持创建和解压 ZIP 文件
超级挑战:实现书签功能,可以保存和快速跳转到常用目录
参考实现:书签功能
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,为前端或移动端提供数据服务!
💪 自我检测
- [ ] 能够独立操作文件和目录
- [ ] 理解绝对路径和相对路径的区别
- [ ] 会处理文件操作的各种异常
- [ ] 掌握递归算法的实现
- [ ] 能够解析和处理用户命令
- [ ] 理解如何与操作系统交互
第四个项目完成了!你已经能够开发实用的系统工具了!最后一个项目,加油!💪
