paint-brush
C# Automation: Using .Net Core To Organize My Downloads Folderby@rizwan3d
447 reads
447 reads

C# Automation: Using .Net Core To Organize My Downloads Folder

by Muhammad RizwanSeptember 26th, 2023
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

The Solution solution is a Bot that loops the download, desktop or any other folder and determines the file type for each and every file. Subsequently, it creates a folder for that file type. All files with the same file type will be transferred to this folder and or Organize by Date.We use.Net Core to make it cross platform. but same code work well for.Net Framework and on Xamarin so it works on every popular device today.
featured image - C# Automation: Using .Net Core To Organize My Downloads Folder
Muhammad Rizwan HackerNoon profile picture

Recently, I felt overly annoyed by my messy download folder on my personal computer. There were too many files, and it was a total mess. I thought to write a simple bot to address this problem.

The Solution

The solution is a bot that loops the download, desktop, or any other folder and determines the file type for each and every file. Subsequently, it creates a folder for that file type. All files with the same file type will be transferred to this folder and/or organized by date.


We use .Net Core to make it cross-platform, but the same code works well for .Net Framework, .Net Standard, and Xamarin, so it works on every popular device today.

Start

Let's start it by creating a new project and initializing git.

dotnet new console -o “FileOrganizer”git initgit add *.*

Working

.Net provides FileSystemWatcher to watch for changes in a specified directory. You can watch for changes in files and sub-directories of the specified directory. You can create a component to watch files on a local computer, a network drive, or a remote computer.


The FileSystemWatcher does not raise events for CDs and DVDs because time stamps and properties cannot change. Remote computers must have one of the required platforms installed for the component to function properly.

using (FileSystemWatcher watcher = new FileSystemWatcher())
{
    watcher.Path = WatchPath;
    watcher.Filter = "*.*";
    watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.CreationTime;

    watcher.Created += OnCreated;
    watcher.EnableRaisingEvents = true;

    Console.WriteLine("Press 'q' to quit.");
    while (Console.Read() != 'q') ;
}

private static void OnCreated(object sender, FileSystemEventArgs e)
{
}

Move File

We make a directory in an Organized path such as File Type, year, Mount, and then date.

private static void OnCreated(object sender, FileSystemEventArgs e)
{
    string watchFilePath = e.FullPath;

    string Extension = Path.GetExtension(watchFilePath).Substring(1);
    if (orgSubPaths.ContainsKey(Extension.ToLower()))
    {
        MoveFile(watchFilePath, orgSubPaths[Extension.ToLower()],Extension);
    }
    else
    {
        MoveFile(watchFilePath, "UnKnown",Extension);
    }
}

private static void MoveFile(string watchFilePath, string orgSubPath,string Extension)
{
    DateTime now = DateTime.Now;
    string year = now.Year.ToString();
    string month = now.ToString("MMMM");
    string day = now.ToString("dd");

    string FileName = Path.GetFileName(watchFilePath);
    string path2ndPart = $@"{orgSubPath}\{year}\{month}\{day}\";
    string FullDirectoryPath = Path.Combine(OrgPath, path2ndPart);

    Directory.CreateDirectory(FullDirectoryPath);          

    File.Move(watchFilePath, OrgEdPath);
}

Error One

It works fine, but when it overwrites the file with the same name, so we add a check.

string OrgEdPath = Path.Combine(FullDirectoryPath, FileName);
if(File.Exists(OrgEdPath)){
    FileName  = $"{Path.GetFileNameWithoutExtension(OrgEdPath)}-{now.Minute}{now.Second}.{Extension}";
    OrgEdPath = Path.Combine(FullDirectoryPath, FileName);
}

Error Two

When the file is pressed, it throws an exception. To overcome this problem, we try to reach the file until the file is open to move.

private static bool IsFileLocked(string FilePath, bool del = false)
{
    bool locked = false;
    try{
        FileStream fs = File.Open(FilePath,FileMode.OpenOrCreate,FileAccess.ReadWrite,FileShare.None);
        fs.Close();
        if(del)
            File.Delete(FilePath);
    }
    catch(Exception){
        locked = true;
    }
    return locked;
}

//so add new lines in MoveFile function.
while(IsFileLocked(watchFilePath) || IsFileLocked(OrgEdPath,true));
  File.Move(watchFilePath, OrgEdPath);

Addition

So, we have to add a configuration file to add or update information without making changes in code and generate logs of files with time.

string[] Config = File.ReadAllLines("Config.csv");

WatchPath = Config[0].Split(',')[1];
OrgPath = Config[1].Split(',')[1];

orgSubPaths = new Dictionary<string, string>();
for(int i = 2;i < Config.Length;i++)
{
    string[] ExtensionOrgSubPath = Config[i].Split(',');
    orgSubPaths.Add(ExtensionOrgSubPath[0], ExtensionOrgSubPath[1]);
}
            
//Add this to end of MoveFunction
File.AppendAllText("Log.csv",$"{now},{watchFilePath},{OrgEdPath}{Environment.NewLine}");

Config File

WatchPath,D:\test\watch
OrgPath,D:\test\org
txt,Word processor and text file
zip,Compressed file
7z,Compressed file
rar,Compressed file
csv,Data and database file
bmp,Image file
gif,Image file
jpeg,Image file
jpg,Image file
png,Image file
doc,Word processor and text file
docx,Word processor and text file
rtf,Word processor and text file
mkv,Video file
mp4,Video file

YouTube Video

Project



Also published here.