วิธีการทำรายการไฟล์ทั้งหมดซ้ำในไดเรกทอรีและไดเรกทอรีลูกใน C #?
วิธีการทำรายการไฟล์ทั้งหมดซ้ำในไดเรกทอรีและไดเรกทอรีลูกใน C #?
คำตอบ:
บทความนี้ครอบคลุมทุกสิ่งที่คุณต้องการ ยกเว้นเมื่อเทียบกับการค้นหาไฟล์และเปรียบเทียบชื่อเพียงพิมพ์ชื่อ
สามารถแก้ไขได้เช่น:
static void DirSearch(string sDir)
{
try
{
foreach (string d in Directory.GetDirectories(sDir))
{
foreach (string f in Directory.GetFiles(d))
{
Console.WriteLine(f);
}
DirSearch(d);
}
}
catch (System.Exception excpt)
{
Console.WriteLine(excpt.Message);
}
}
เพิ่มโดย barlop
GONeale กล่าวว่าข้างต้นไม่ได้แสดงรายการไฟล์ในไดเรกทอรีปัจจุบันและแนะนำให้วางส่วนรายการไฟล์ไว้นอกส่วนที่รับไดเรกทอรี ต่อไปนี้จะทำเช่นนั้น นอกจากนี้ยังมีบรรทัด Writeline ที่คุณสามารถยกเลิกหมายเหตุซึ่งช่วยในการติดตามตำแหน่งที่คุณอยู่ในการสอบถามซ้ำซึ่งอาจช่วยในการแสดงการโทรเพื่อช่วยแสดงวิธีการเรียกซ้ำ
DirSearch_ex3("c:\\aaa");
static void DirSearch_ex3(string sDir)
{
//Console.WriteLine("DirSearch..(" + sDir + ")");
try
{
Console.WriteLine(sDir);
foreach (string f in Directory.GetFiles(sDir))
{
Console.WriteLine(f);
}
foreach (string d in Directory.GetDirectories(sDir))
{
DirSearch_ex3(d);
}
}
catch (System.Exception excpt)
{
Console.WriteLine(excpt.Message);
}
}
โปรดทราบว่าใน. NET 4.0 มีฟังก์ชั่นไฟล์ iterator-based (แทนที่จะใช้ array) ที่สร้างขึ้นใน:
foreach (string file in Directory.EnumerateFiles(path, "*.*", SearchOption.AllDirectories))
{
Console.WriteLine(file);
}
ในตอนนี้ฉันจะใช้บางอย่างเช่นด้านล่าง; วิธีการเรียกซ้ำแบบ inbuilt แบ่งง่ายเกินไปหากคุณไม่สามารถเข้าถึง sub-dir เดียว ... ; การQueue<string>
ใช้งานหลีกเลี่ยงการโทรซ้ำซ้อนกันมากเกินไปและตัวบล็อกตัววนซ้ำทำให้เราไม่ได้รับข้อมูลมากมาย
static void Main() {
foreach (string file in GetFiles(SOME_PATH)) {
Console.WriteLine(file);
}
}
static IEnumerable<string> GetFiles(string path) {
Queue<string> queue = new Queue<string>();
queue.Enqueue(path);
while (queue.Count > 0) {
path = queue.Dequeue();
try {
foreach (string subDir in Directory.GetDirectories(path)) {
queue.Enqueue(subDir);
}
}
catch(Exception ex) {
Console.Error.WriteLine(ex);
}
string[] files = null;
try {
files = Directory.GetFiles(path);
}
catch (Exception ex) {
Console.Error.WriteLine(ex);
}
if (files != null) {
for(int i = 0 ; i < files.Length ; i++) {
yield return files[i];
}
}
}
}
*.*
มีไฟล์ที่ไม่มีนามสกุลไฟล์หรือไม่ : ใช่มีการทดสอบเมื่อนาทีที่แล้ว
using System.IO;
Console
คุณจะต้องเพิ่มusing System;
- แต่เนื่องจาก IDE สามารถเพิ่มusing
คำสั่งที่จำเป็นทั้งหมดสำหรับคุณ (ctrl +.) และเนื่องจากเราไม่ได้ใช้สิ่งแปลกใหม่ที่นี่จึงเป็นเรื่องปกติที่จะไม่รวมไว้ Heck คุณจะต้องมีclass
คำจำกัดความอื่น ๆ เพียงแค่บอกว่า '
Directory.GetFiles("C:\\", "*.*", SearchOption.AllDirectories)
ใน. NET 4.5 อย่างน้อยมีรุ่นนี้ที่สั้นกว่ามากและมีโบนัสเพิ่มเติมในการประเมินเกณฑ์ไฟล์ใด ๆ เพื่อรวมไว้ในรายการ:
public static IEnumerable<string> GetAllFiles(string path,
Func<FileInfo, bool> checkFile = null)
{
string mask = Path.GetFileName(path);
if (string.IsNullOrEmpty(mask)) mask = "*.*";
path = Path.GetDirectoryName(path);
string[] files = Directory.GetFiles(path, mask, SearchOption.AllDirectories);
foreach (string file in files)
{
if (checkFile == null || checkFile(new FileInfo(file)))
yield return file;
}
}
ใช้แบบนี้:
var list = GetAllFiles(mask, (info) => Path.GetExtension(info.Name) == ".html").ToList();
IEnumerable<string> GetFilesFromDir(string dir) =>
Directory.EnumerateFiles(dir).Concat(
Directory.EnumerateDirectories(dir)
.SelectMany(subdir => GetFilesFromDir(subdir)));
ใน Framework 2.0 คุณสามารถใช้ (เป็นรายการไฟล์ของโฟลเดอร์ root คำตอบยอดนิยมที่ดีที่สุด):
static void DirSearch(string dir)
{
try
{
foreach (string f in Directory.GetFiles(dir))
Console.WriteLine(f);
foreach (string d in Directory.GetDirectories(dir))
{
Console.WriteLine(d);
DirSearch(d);
}
}
catch (System.Exception ex)
{
Console.WriteLine(ex.Message);
}
}
บางคำตอบที่ยอดเยี่ยม แต่คำตอบเหล่านี้ไม่ได้แก้ปัญหาของฉัน
ทันทีที่เกิดปัญหาการอนุญาตให้โฟลเดอร์: "การอนุญาตถูกปฏิเสธ" รหัสล้มเหลว นี่คือสิ่งที่ฉันใช้เพื่อแก้ไขปัญหา "สิทธิ์การปฏิเสธ":
private int counter = 0;
private string[] MyDirectories = Directory.GetDirectories("C:\\");
private void ScanButton_Click(object sender, EventArgs e)
{
Thread MonitorSpeech = new Thread(() => ScanFiles());
MonitorSpeech.Start();
}
private void ScanFiles()
{
string CurrentDirectory = string.Empty;
while (counter < MyDirectories.Length)
{
try
{
GetDirectories();
CurrentDirectory = MyDirectories[counter++];
}
catch
{
if (!this.IsDisposed)
{
listBox1.Invoke((MethodInvoker)delegate { listBox1.Items.Add("Access Denied to : " + CurrentDirectory); });
}
}
}
}
private void GetDirectories()
{
foreach (string directory in MyDirectories)
{
GetFiles(directory);
}
}
private void GetFiles(string directory)
{
try
{
foreach (string file in Directory.GetFiles(directory, "*"))
{
listBox1.Invoke((MethodInvoker)delegate { listBox1.Items.Add(file); });
}
}
catch
{
listBox1.Invoke((MethodInvoker)delegate { listBox1.Items.Add("Access Denied to : " + directory); });
}
}
หวังว่านี่จะช่วยผู้อื่น
ทางออกที่ง่ายและสะอาด
/// <summary>
/// Scans a folder and all of its subfolders recursively, and updates the List of files
/// </summary>
/// <param name="sFullPath">Full path of the folder</param>
/// <param name="files">The list, where the output is expected</param>
internal static void EnumerateFiles(string sFullPath, List<FileInfo> fileInfoList)
{
try
{
DirectoryInfo di = new DirectoryInfo(sFullPath);
FileInfo[] files = di.GetFiles();
foreach (FileInfo file in files)
fileInfoList.Add(file);
//Scan recursively
DirectoryInfo[] dirs = di.GetDirectories();
if (dirs == null || dirs.Length < 1)
return;
foreach (DirectoryInfo dir in dirs)
EnumerateFiles(dir.FullName, fileInfoList);
}
catch (Exception ex)
{
Logger.Write("Exception in Helper.EnumerateFiles", ex);
}
}
ฉันชอบที่จะใช้ DirectoryInfo เพราะฉันสามารถรับ FileInfo ไม่ใช่แค่สตริง
string baseFolder = @"C:\temp";
DirectoryInfo di = new DirectoryInfo(baseFolder);
string searchPattern = "*.xml";
ICollection<FileInfo> matchingFileInfos = di.GetFiles(searchPattern, SearchOption.AllDirectories)
.Select(x => x)
.ToList();
ฉันทำสิ่งนี้ในอนาคตฉันต้องการการกรองในอนาคต .. อิงตามคุณสมบัติของ FileInfo
string baseFolder = @"C:\temp";
DirectoryInfo di = new DirectoryInfo(baseFolder);
string searchPattern = "*.xml";
ICollection<FileInfo> matchingFileInfos = di.GetFiles(searchPattern, SearchOption.AllDirectories)
.Where(x => x.LastWriteTimeUtc < DateTimeOffset.Now)
.Select(x => x)
.ToList();
ฉันยังสามารถหันกลับไปที่สตริงถ้าจำเป็น (และยังคงได้รับการพิสูจน์ในอนาคตสำหรับตัวกรอง / สิ่งที่ข้อ -
string baseFolder = @"C:\temp";
DirectoryInfo di = new DirectoryInfo(baseFolder);
string searchPattern = "*.xml";
ICollection<string> matchingFileNames = di.GetFiles(searchPattern, SearchOption.AllDirectories)
.Select(x => x.FullName)
.ToList();
โปรดทราบว่า " . " เป็นรูปแบบการค้นหาที่ถูกต้องหากคุณต้องการกรองตามนามสกุล
private void GetFiles(DirectoryInfo dir, ref List<FileInfo> files)
{
try
{
files.AddRange(dir.GetFiles());
DirectoryInfo[] dirs = dir.GetDirectories();
foreach (var d in dirs)
{
GetFiles(d, ref files);
}
}
catch (Exception e)
{
}
}
files
คือref
? ไม่มีความจําเป็น.
files
และคุณไม่สามารถให้new List<FileInfo>()
เป็นพารามิเตอร์อีกต่อไปซึ่งจะไร้ประโยชน์ อาจอนุญาตให้มีการเพิ่มประสิทธิภาพย่อยบางอย่างและหลีกเลี่ยงการสร้างวัตถุใหม่เว้นแต่จำเป็นต้องใช้
ref
อย่าทำให้ชัดเจน ref
's วัตถุประสงค์คือการเปลี่ยนทั้งfiles
ตัวชี้แม้สำหรับผู้โทรวิธีการ: ก็ดำเนินการที่เป็นอันตรายและที่นี่มีความจำเป็นสำหรับการที่ไม่มีคุณก็สามารถกรอกรายการที่คุณไม่จำเป็นต้องไปอีกจุดไปยังรายการอื่น กอง ref
ควรใช้ในกรณีพิเศษเท่านั้น เวลาส่วนใหญ่คุณเพียงแค่ต้องใช้สิ่งต่าง ๆ ในวิธีการทำงานแบบกระบวนทัศน์มากขึ้น
เพื่อหลีกเลี่ยงการUnauthorizedAccessException
ฉันใช้:
var files = GetFiles(@"C:\", "*.*", SearchOption.AllDirectories);
foreach (var file in files)
{
Console.WriteLine($"{file}");
}
public static IEnumerable<string> GetFiles(string path, string searchPattern, SearchOption searchOption)
{
var foldersToProcess = new List<string>()
{
path
};
while (foldersToProcess.Count > 0)
{
string folder = foldersToProcess[0];
foldersToProcess.RemoveAt(0);
if (searchOption.HasFlag(SearchOption.AllDirectories))
{
//get subfolders
try
{
var subfolders = Directory.GetDirectories(folder);
foldersToProcess.AddRange(subfolders);
}
catch (Exception ex)
{
//log if you're interested
}
}
//get files
var files = new List<string>();
try
{
files = Directory.GetFiles(folder, searchPattern, SearchOption.TopDirectoryOnly).ToList();
}
catch (Exception ex)
{
//log if you're interested
}
foreach (var file in files)
{
yield return file;
}
}
}
หากคุณต้องการชื่อไฟล์และเนื่องจากฉันไม่ชอบวิธีแก้ไขปัญหาส่วนใหญ่ที่นี่ (คุณสมบัติที่ใช้งานง่ายหรืออ่านง่าย) แล้วอันที่ขี้เกียจนี้ล่ะ
private void Foo()
{
var files = GetAllFiles("pathToADirectory");
foreach (string file in files)
{
// Use can use Path.GetFileName() or similar to extract just the filename if needed
// You can break early and it won't still browse your whole disk since it's a lazy one
}
}
/// <exception cref="T:System.IO.DirectoryNotFoundException">The specified path is invalid (for example, it is on an unmapped drive).</exception>
/// <exception cref="T:System.UnauthorizedAccessException">The caller does not have the required permission.</exception>
/// <exception cref="T:System.IO.IOException"><paramref name="path" /> is a file name.-or-A network error has occurred.</exception>
/// <exception cref="T:System.IO.PathTooLongException">The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters and file names must be less than 260 characters.</exception>
/// <exception cref="T:System.ArgumentNullException"><paramref name="path" /> is null.</exception>
/// <exception cref="T:System.ArgumentException"><paramref name="path" /> is a zero-length string, contains only white space, or contains one or more invalid characters as defined by <see cref="F:System.IO.Path.InvalidPathChars" />.</exception>
[NotNull]
public static IEnumerable<string> GetAllFiles([NotNull] string directory)
{
foreach (string file in Directory.GetFiles(directory))
{
yield return file; // includes the path
}
foreach (string subDir in Directory.GetDirectories(directory))
{
foreach (string subFile in GetAllFiles(subDir))
{
yield return subFile;
}
}
}
บันทึกที่สั้นที่สุด
string files = Directory.GetFiles(@"your_path", "*.jpg", SearchOption.AllDirectories);
นี่คือมุมมองของฉันตาม Hernaldo ถ้าคุณต้องการค้นหาไฟล์ที่มีชื่อของรูปแบบบางอย่างเช่นไฟล์ XML ที่บางแห่งในชื่อมีสตริงเฉพาะ:
// call this like so: GetXMLFiles("Platypus", "C:\\");
public static List<string> GetXMLFiles(string fileType, string dir)
{
string dirName = dir;
var fileNames = new List<String>();
try
{
foreach (string f in Directory.GetFiles(dirName))
{
if ((f.Contains(fileType)) && (f.Contains(".XML")))
{
fileNames.Add(f);
}
}
foreach (string d in Directory.GetDirectories(dirName))
{
GetXMLFiles(fileType, d);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return fileNames;
}
รายการไฟล์และโฟลเดอร์ไปยังรูปแบบการใช้งานที่กำหนดเอง
สิ่งนี้จะสร้างรายชื่อไฟล์และโฟลเดอร์ทั้งหมดที่เริ่มต้นจากไดเรกทอรีเริ่มต้นของคุณ
public class DirOrFileModel
{
#region Private Members
private string _name;
private string _location;
private EntryType _entryType;
#endregion
#region Bindings
public string Name
{
get { return _name; }
set
{
if (value == _name) return;
_name = value;
}
}
public string Location
{
get { return _location; }
set
{
if (value == _location) return;
_location = value;
}
}
public EntryType EntryType
{
get { return _entryType; }
set
{
if (value == _entryType) return;
_entryType = value;
}
}
public ObservableCollection<DirOrFileModel> Entries { get; set; }
#endregion
#region Constructor
public DirOrFileModel()
{
Entries = new ObservableCollection<DirOrFileModel>();
}
#endregion
}
public enum EntryType
{
Directory = 0,
File = 1
}
วิธี:
static DirOrFileModel DirSearch(DirOrFileModel startDir)
{
var currentDir = startDir;
try
{
foreach (string d in Directory.GetDirectories(currentDir.Location))
{
var newDir = new DirOrFileModel
{
EntryType = EntryType.Directory,
Location = d,
Name = Path.GetFileName(d)
};
currentDir.Entries.Add(newDir);
DirSearch(newDir);
}
foreach (string f in Directory.GetFiles(currentDir.Location))
{
var newFile = new DirOrFileModel
{
EntryType = EntryType.File,
Location = f,
Name = Path.GetFileNameWithoutExtension(f)
};
currentDir.Entries.Add(newFile);
}
}
catch (Exception excpt)
{
Console.WriteLine(excpt.Message);
}
return startDir;
}
การใช้งาน:
var dir = new DirOrFileModel
{
Name = "C",
Location = @"C:\",
EntryType = EntryType.Directory
};
dir = DirSearch(dir);
วิธีแก้ปัญหาสั้นและง่าย
string dir = @"D:\PATH";
DateTime from_date = DateTime.Now.Date;
DateTime to_date = DateTime.Now.Date.AddHours(23);
var files = Directory.EnumerateFiles(dir, "*.*",SearchOption.AllDirectories).Select(i=>new FileInfo(i))
.Where(file=>file.LastWriteTime >= from_date && file.LastWriteTime <= to_date);
foreach(var fl in files)
Console.WriteLine(fl.FullName);
อันนี้ช่วยให้ฉันได้รับไฟล์ทั้งหมดในไดเรกทอรีและไดเรกทอรีย่อยอาจเป็นประโยชน์สำหรับใครบางคน [รับแรงบันดาลใจจากคำตอบข้างต้น]
static void Main(string[] args)
{
try
{
var root = @"G:\logs";
DirectorySearch(root);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadKey();
}
public static void DirectorySearch(string root, bool isRootItrated = false)
{
if (!isRootItrated)
{
var rootDirectoryFiles = Directory.GetFiles(root);
foreach (var file in rootDirectoryFiles)
{
Console.WriteLine(file);
}
}
var subDirectories = Directory.GetDirectories(root);
if (subDirectories?.Any() == true)
{
foreach (var directory in subDirectories)
{
var files = Directory.GetFiles(directory);
foreach (var file in files)
{
Console.WriteLine(file);
}
DirectorySearch(directory, true);
}
}
}
var d = new DirectoryInfo(@"C:\logs");
var list = d.GetFiles("*.txt").Select(m => m.Name).ToList();
บางรุ่นที่ได้รับการปรับปรุงพร้อม max lvl เพื่อลงไปในไดเรกทอรีและตัวเลือกเพื่อแยกโฟลเดอร์:
using System;
using System.IO;
class MainClass {
public static void Main (string[] args) {
var dir = @"C:\directory\to\print";
PrintDirectoryTree(dir, 2, new string[] {"folder3"});
}
public static void PrintDirectoryTree(string directory, int lvl, string[] excludedFolders = null, string lvlSeperator = "")
{
excludedFolders = excludedFolders ?? new string[0];
foreach (string f in Directory.GetFiles(directory))
{
Console.WriteLine(lvlSeperator+Path.GetFileName(f));
}
foreach (string d in Directory.GetDirectories(directory))
{
Console.WriteLine(lvlSeperator + "-" + Path.GetFileName(d));
if(lvl > 0 && Array.IndexOf(excludedFolders, Path.GetFileName(d)) < 0)
{
PrintDirectoryTree(d, lvl-1, excludedFolders, lvlSeperator+" ");
}
}
}
}
ไดเรกทอรีอินพุต:
-folder1
file1.txt
-folder2
file2.txt
-folder5
file6.txt
-folder3
file3.txt
-folder4
file4.txt
file5.txt
เอาท์พุทของฟังก์ชั่น (เนื้อหาของ folder5 ถูกแยกออกเนื่องจากข้อ จำกัด lvl และเนื้อหาของ folder3 ถูกแยกออกเนื่องจากอยู่ในอาร์เรย์แยกออกของOLD):
-folder1
file1.txt
-folder2
file2.txt
-folder5
-folder3
-folder4
file4.txt
file5.txt
นี่คือรุ่นของรหัส B. Clay Shannon ที่ไม่คงที่สำหรับไฟล์ excel:
class ExcelSearcher
{
private List<string> _fileNames;
public ExcelSearcher(List<string> filenames)
{
_fileNames = filenames;
}
public List<string> GetExcelFiles(string dir, List<string> filenames = null)
{
string dirName = dir;
var dirNames = new List<string>();
if (filenames != null)
{
_fileNames.Concat(filenames);
}
try
{
foreach (string f in Directory.GetFiles(dirName))
{
if (f.ToLower().EndsWith(".xls") || f.ToLower().EndsWith(".xlsx"))
{
_fileNames.Add(f);
}
}
dirNames = Directory.GetDirectories(dirName).ToList();
foreach (string d in dirNames)
{
GetExcelFiles(d, _fileNames);
}
}
catch (Exception ex)
{
//Bam
}
return _fileNames;
}
ทางออกที่ง่ายมากส่งคืนรายการไฟล์
public static List<string> AllFilesInFolder(string folder)
{
var result = new List<string>();
foreach (string f in Directory.GetFiles(folder))
{
result.Add(f);
}
foreach (string d in Directory.GetDirectories(folder))
{
result.AddRange(AllFilesInFolder(d));
}
return result;
}
static void Main(string[] args)
{
string[] array1 = Directory.GetFiles(@"D:\");
string[] array2 = System.IO.Directory.GetDirectories(@"D:\");
Console.WriteLine("--- Files: ---");
foreach (string name in array1)
{
Console.WriteLine(name);
}
foreach (string name in array2)
{
Console.WriteLine(name);
}
Console.ReadLine();
}