CodeGym /Kurslar /C# SELF /Fayllarla kütləvi əməliyyatlar

Fayllarla kütləvi əməliyyatlar

C# SELF
Səviyyə , Dərs
Mövcuddur

1. Giriş

Bir neçə il ərzində toplanmış fotoarxivi təsəvvür edin — bir qovluqda minlərlə fayl (Windows istifadəçisi üçün klassika), indi isə vəzifəni düşünün: yalnız bu il yaradılmış .jpg fayllarını emal üçün ayrı qovluğa kopyalamaq. Və ya bütün hesabatları "old_" prefiksi ilə yenidən adlandırmaq lazım gəlsin ki, köhnə və yeni versiyanı ayırd edesiniz. Fotoarxivlərdən uzaq olsanız belə, kütləvi əməliyyatlar demək olar hər hansı data emalı, loglar, backup və ya avtomatlaşdırma layihəsində lazım olur. Onlar hətta müsahibələrdə də çıxır!

Kütləvi əməliyyatlar aşağıdakılar üçün yaxşı fürsətdir:

  • Döngülər və LINQ ilə direktoriyaların məzmununu iterasiya etmək
  • Yollarla (Path) işləmək praktikası
  • Filtrləmə, axtarış, şablon üzrə yenidən adlandırmanın əsasları
  • Vacib məsələlər: təhlükəsizlik, səhvlər, overwrite

Başlayaq — və fayl xaosunu məğlub etmək gücü sizinlə olsun!

2. Faylların kütləvi kopyalanması

Necə işləyir: ümumi prinsip

Kütləvi əməliyyat üçün adətən lazım olur:

  1. Lazımlı faylların siyahısını almaq (məsələn, qovluqdakı bütün .txt)
  2. Hər fayl üçün tələb olunan əməliyyatı icra etmək (kopyalama, silmə və s.)

Bunu aşağıdakılarla reallaşdırmaq olar:

  • Directory.GetFiles() — fayl siyahısını əldə etmək,
  • Döngü foreach — hər faylı keçib lazımi əməliyyatı icra etmək.

Nümunə: bir qovluqdan digərinə bütün .txt faylları kopyalamaq


string sourceDir = @"C:\Source";
string destDir = @"C:\Target";

// Mənbə qovluğundakı bütün .txt faylların siyahısını alırıq
string[] txtFiles = Directory.GetFiles(sourceDir, "*.txt");

foreach (string srcPath in txtFiles)
{
    // Tam yoldan yalnız fayl adını alırıq
    string fileName = Path.GetFileName(srcPath);

    // Hədəf qovluqda fayl üçün tam yolu formalaşdırırıq
    string destPath = Path.Combine(destDir, fileName);

    // Faylı kopyalayırıq
    File.Copy(srcPath, destPath, overwrite: true); // overwrite - əgər fayl varsa, əvəz et
    Console.WriteLine($"Copied: {fileName}");
}

Console.WriteLine("Bütün .txt fayllar uğurla kopyalandı!");

Nəzərə alın: bu nümunədə biz "*.txt" filtrindən istifadə edirik — bu Windows-da fayl adlarının axtarışı üçün pattern-dir.

Vizualizasiya (sxem)

+----------------+     [*.txt]     +----------------+
|   C:\Source    | ---filter-----> |   C:\Target    |
| a.txt          |   foreach +     |                |
| b.txt          | --copy--------> | a.txt (copied) |
| c.jpg          |                | b.txt (copied) |
+----------------+                +----------------+
(.jpg fayllar nəzərə alınmır, yalnız .txt kopyalanır)

3. Faylların kütləvi silinməsi

Faylların kütləvi silinməsi — çox yayılmış əməliyyatdır. Məsələn, tez-tez müvəqqəti faylların təmizlənməsi, köhnə logların avtomatik silinməsi və ya artıq lazım olmayan jpg-fotoların çıxarılması tələb olunur.

Nümunə: 30 gündən köhnə bütün faylları silirik


string dir = @"C:\MyLogs";
int daysOld = 30;

DirectoryInfo di = new DirectoryInfo(dir);
// Qovluqdakı bütün faylları alırıq
foreach (FileInfo file in di.GetFiles())
{
    // Son dəyişmə tarixini yoxlayırıq
    if (file.LastWriteTime < DateTime.Now.AddDays(-daysOld))
    {
        file.Delete();
        Console.WriteLine($"Silindi: {file.Name}");
    }
}

Hack: FileInfo.LastWriteTime — "N günündən köhnə" şərtləri üçün çox rahatdır.

4. Faylların kütləvi yenidən adlandırılması

Bəzən faylları şablona əsasən yenidən adlandırmaq lazım olur. Məsələn, ümumi prefiks əlavə etmək, extension-u dəyişdirmək və ya sadəcə ardıcıl nömrələmək. .NET-də bu da oxşar şəkildə edilir — fayl siyahısını alırsınız, sonra File.Move() ilə adını dəyişirsiniz.

Nümunə: bütün .docx fayllara "old_" prefiksi əlavə edək


string dir = @"C:\Reports";

string[] docxFiles = Directory.GetFiles(dir, "*.docx");
foreach (string oldPath in docxFiles)
{
    string dirPath = Path.GetDirectoryName(oldPath)!;
    string fileName = Path.GetFileName(oldPath);
    string newPath = Path.Combine(dirPath, "old_" + fileName);

    // Yenidən adlandırırıq (əsasən eyni qovluqda yeni adla "hərəkət")
    File.Move(oldPath, newPath);
    Console.WriteLine($"Yenidən adlandırıldı: {fileName} -> old_{fileName}");
}

Vacib məqam: əgər qovluqda artıq yeni adla fayl varsa, istisna yaranacaq. Lazımdırsa bunu try-catch ilə işləmək olar.

5. Bütün direktoriyaları məzmuna görə kopyalamaq

Sadə bir qovluq əməliyyatları üçün bir sətrlik "kopyala bütün qovluğu" vasitəsi yoxdur (Directory.Copy yoxdur — bu jedi-lər üçün tələyə oxşayır!). Əllə kopyalamağa məcbursunuz:

  1. Hədəf qovluğu yaradın (əgər yoxdursa)
  2. Bütün faylları kopyalayın (tanış nümunəyə baxın)
  3. Bütün altqovluqları rekursiv şəkildə kopyalayın (hər birini yeni kopyalama tapşırığı kimi işləyin)

Universal funksiya: qovluğu rekursiv surətdə kopyalamaq


using System;
using System.IO;

class Program
{
    static void CopyDirectory(string sourceDir, string destDir, bool overwrite = true)
    {
        // Qovluğu yaradın, əgər yoxdursa
        Directory.CreateDirectory(destDir);

        // Bütün faylları kopyalayırıq
        foreach (string filePath in Directory.GetFiles(sourceDir))
        {
            string fileName = Path.GetFileName(filePath);
            string destFile = Path.Combine(destDir, fileName);
            File.Copy(filePath, destFile, overwrite);
        }

        // Bütün altqovluqları rekursiv surətdə kopyalayırıq
        foreach (string subDir in Directory.GetDirectories(sourceDir))
        {
            string dirName = Path.GetFileName(subDir);
            string destSubDir = Path.Combine(destDir, dirName);
            CopyDirectory(subDir, destSubDir, overwrite);
        }
    }

    static void Main()
    {
        string source = @"C:\Archive2023";
        string target = @"D:\Backup2023";
        CopyDirectory(source, target);
        Console.WriteLine("Qovluq uğurla kopyalandı!");
    }
}

Blok-sxema

            CopyDirectory(A, B)
               /          \
      copy files        foreach subDir -> CopyDirectory(subDir, destSubDir)

6. Kütləvi filtrasiya, axtarış və faylların emalı

Tutaq ki, yalnız qovluğu sıralamaq kifayət deyil, bir neçə meyara görə seçmək istəyirsiniz: məsələn, yalnız ölçüsü 5 MB-dən böyük olan şəkillər və onlar 2024 ildə yaradılıblar! Bunun üçün LINQ-i file system sinifləri ilə birləşdirmək rahatdır.

Nümunə: böyük və yenilənmiş şəkillərin adlarını çıxardırıq


string dir = @"C:\Pictures";

var filtered = new DirectoryInfo(dir)
    .GetFiles("*.jpg")
    .Where(f => f.Length > 5_000_000 && f.CreationTime.Year == 2024);

foreach (var file in filtered)
{
    Console.WriteLine($"{file.Name} ({file.Length / 1024 / 1024} МБ)");
}

Bu nümunədə biz filtrləmə zəncirləri üçün LINQ istifadə edirik — real işdə rast gəlinən kod yazırıq.

7. İçi-içə qovluqlarda dolaşma: rekursiya və iterasiya

Tez-tez yalnız bir direktoriyanı yox, bütün daxil olanları da işləmək lazımdır (məsələn, arxiv strukturunun bütünündə müvəqqəti faylları silmək). Fayl alma metodlarının (Directory.GetFilesDirectoryInfo.GetFiles) SearchOption.AllDirectories parametr variantı var — bu işin hamısını sizin üçün edəcək!

Nümunə: bütün altqovluqlarda bütün .tmp faylları tapıb silmək


string root = @"D:\BigFolder";
string[] tmpFiles = Directory.GetFiles(root, "*.tmp", SearchOption.AllDirectories);

foreach (string file in tmpFiles)
{
    File.Delete(file);
    Console.WriteLine($"Silindi: {file}");
}
Console.WriteLine("Bütün müvəqqəti fayllar silindi.");

Diqqət: bu flag ilə ehtiyatlı olun — çox dərin iç-içə strukturlarda da faylları tapa bilər!

8. Faylların və direktoriyaların kütləvi yaradılması

Bəzən əksinə vəzifə olur — avtomatik olaraq lazım olan qovluq strukturunu yaratmaq və ya çoxlu fayllar generasiya etmək.

Nümunə: hər birində 10 fayl olmaqla 10 qovluq yaratmaq


string root = @"C:\GeneratedFolders";

for (int i = 1; i <= 10; i++)
{
    string subDir = Path.Combine(root, $"Folder_{i}");
    Directory.CreateDirectory(subDir);

    for (int j = 1; j <= 10; j++)
    {
        string filePath = Path.Combine(subDir, $"File_{j}.txt");
        File.WriteAllText(filePath, $"Bu fayl №{j} qovluqda {i}-dir");
    }
}

Console.WriteLine("Qovluqlar və fayllar yaradıldı!");

Hack: Test infrastrukturunu sürətlə yığmaq, test üçün "fish" generasiya etmək, təlim və s. üçün faydalıdır.

9. Faylların kütləvi hərəkət etdirilməsi

Kopyalama ilə analoji, yalnız File.Copy deyil, File.Move istifadə olunur. Faylları qovluqlara çeşidləmək üçün yaxşıdır.

Nümunə: faylları extension üzrə çeşidləyirik

Təsəvvür edin, qovluqda müxtəlif tip fayllar var və siz onları .jpg, .pdf, .docx və s. qovluqlara ayırmaq istəyirsiniz.


string source = @"C:\Downloads";
string[] files = Directory.GetFiles(source);

foreach (string path in files)
{
    string ext = Path.GetExtension(path).TrimStart('.').ToUpper(); // "JPG", "PDF", "DOCX"
    if (string.IsNullOrEmpty(ext)) ext = "OTHER";
    string destDir = Path.Combine(source, ext);

    Directory.CreateDirectory(destDir); // artıq varsa problem deyil

    string fileName = Path.GetFileName(path);
    string destPath = Path.Combine(destDir, fileName);

    if (!File.Exists(destPath))
    {
        File.Move(path, destPath);
        Console.WriteLine($"Hərəkət etdirildi: {fileName} -> {destDir}");
    }
    else
    {
        Console.WriteLine($"Fayl artıq {destDir}-də mövcuddur, keçirilmədi: {fileName}");
    }
}

Fayllar "qutulara" ayrılacaq və siz özünüzü digital Marie Kondo kimi hiss edəcəksiniz.

10. Kütləvi əməliyyatların tipik səhvləri və incəlikləri

Bir faylla deyil, yüzlərlə ilə işləyəndə maraqlı məqamlar ortaya çıxır.

Məsələn, bəzi fayllar başqa proqram tərəfindən açıq ola bilər — onları silmək və ya kopyalamaq cəhdi səhvə gətirəcək. Həmçinin hədəf qovluqda artıq lazım olan adla faylın olması tez-tez rast gəlinir. Əgər kod overwrite-u nəzərdə tutmursa, istisna ilə crash olacaq. Bəzən faylların və qovluqların icazələri yoxdur və ya siz təsadüfən vacib bir şeyi rekursiv şəkildə silə bilərsiniz.

Klassik səhv — əməliyyatları səhv emalı olmadan icra etmək: ortada nəsə səhv olarsa (məsələn, bir fayla giriş icazəsi yoxdursa), döngü dayanacaq və sonrakı fayllar işlənməyəcək. Buna görə də etibarlı kütləvi əməliyyatlarda adətən döngü içərisində try-catch ilə istisnaları tutmaq məsləhətdir ki, problemli faylı keçib qalanları işlətmək mümkün olsun.

Və overwrite parametrlərini unutmayın: lazımi yerlərdə overwrite: true istifadə edin File.Copy-da, ad dəyişmə/hərəkət əməliyyatlarında isə hədəf yolu yoxlayın və ya konflikt strategiyası tətbiq edin (suffix ilə yenidən adlandırma, keçmə, jurnal yazma və s.).

1
Sorğu/viktorina
, səviyyə, dərs
Əlçatan deyil
Faylların yaradılması və silinməsi
Fayllar və qovluqların idarə olunması
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION