This program moves files to a backup directory, archiving them by year of last modification.From a directory like :. file1.ext file2.ext file3.ext fileN.extTo destination:. _Backup|    2002|   _200X|       file3.ext|       fileN.ext file1.ext file2.extConfiguration.xml:<?xml version=1.0 encoding=utf-8 ?><data>  <PathItem PathFrom=C:\Test\FjournaTest             PathTo  =C:\Test\FjournaTest\bak             Delay=20 Enable=1 />  <PathItem PathFrom=\\AAAAAAA\BBB\Commun\Email\XYZ\             PathTo  =\\AAAAAAA\BBB\Commun\Email\XYZ\Backup             Delay=30 Enable=0 /></data>Delay is the number of days old the file needs to be eligible to the backup.FileMover.Csclass FileMove{    private IEnumerable<PathItem> _pathList;    private bool _Talk = false;    private DateTime currentDate = DateTime.Now;    private int tryMAX = 7;    public FileMove(string configPath)    {        if (!PathValid(configPath))        {            throw new Exception($Invalid Configuration Path: [{configPath}].);        }        XDocument doc = XDocument.Load(configPath);        var tempP = from p in doc.Descendants(PathItem)                    where int.Parse(p.Attributes(Enable).First().Value) == 1                    select                     new PathItem(                        p.Attributes(PathFrom).First().Value                        , p.Attributes(PathTo).First().Value                        , int.Parse(p.Attributes(Delay).First().Value)                        , true                    );        //Distinct on From.         _pathList = tempP.GroupBy(                            i => i.PathFrom,                            (key, group) => group.First()                        ).ToArray();    }    public FileMove(string configPath, bool talk) : this(configPath)    {        this._Talk = talk;    }    public void Run()    {        if (!_pathList.Any())        {            W(No Enabled Path.);            return;        }        I(Process Start.);        foreach (var x in _pathList)        {            I($Processing:\n{x});//TODO Try > Catch > Log.            Process(x.PathFrom, x.PathTo, x.Delay);        }        I(Process End.);    }    private void Process(string pathFrom, string pathTo, int delay)    {        bool ValidPathFrom = PathValid(pathFrom)             , ValidPathTo = PathValid(pathTo);        if (!(ValidPathFrom && ValidPathTo))        {            W(Path Not Valid!);            W($\tPathFrom:{ValidPathFrom}\tPathTo:{ValidPathTo});            return;        }        I($\tPath Valid  >PathFrom:{pathFrom}\t>PathTo:{pathTo});        string[] fileEntries = Directory.GetFiles(pathFrom);        Parallel.ForEach(fileEntries, (fileName) =>        {            ProcessFile(fileName, pathTo, delay);        });    }    private void ProcessFile(string fileName, string pathTo, int delay)    {        var fileInfo = new FileInfo(fileName);        DateTime lastModified = fileInfo.LastWriteTime;        int DuplicateCounter = 0;        var yearDirectory = lastModified.Year.ToString();        string shortName = Path.GetFileNameWithoutExtension(fileInfo.Name);        pathTo += $\\{yearDirectory};        string savePath = ${pathTo}\\{fileInfo.Name};        if (delay == 0 || (currentDate - lastModified).Days >= delay)        {            //Year Dir Exist ?            if (!PathValid(pathTo))            {                Directory.CreateDirectory(pathTo);            }            // Make sure that the target does not exist.            while (File.Exists(savePath) && DuplicateCounter < 99)            {                DuplicateCounter++;                savePath = ${pathTo}\\{shortName}({DuplicateCounter}){fileInfo.Extension};                if (DuplicateCounter == 99) {                     W($\t\t[{shortName}] Have to many duplicate.);                }            }            // MoveIt.            int tryCount = 0;            while (tryCount < tryMAX + 1)            {                try                {                    fileInfo.MoveTo(savePath);                }                catch (Exception e)                {                    if (tryCount == tryMAX)                    {//thinks 7 time before it speaks                        throw new Exception($-File move : {savePath} #Failed, e);                    }                    tryCount++;                    continue;                }                break;            }            I({0} was moved to {1}., fileName, savePath);        }    }    private bool PathValid(string path)    {        if (File.Exists(path))        {            return true;        }        else if (Directory.Exists(path))        {            return true;        }        else        {            W({0} is not a valid directory or file., path);            return false;        }    }    private bool PathValid(string path, out bool validPathFrom)    {        validPathFrom = PathValid(path);        return validPathFrom;    }    public void W(string format, params object[] args)  //Warning always printed    {    #if DEBUG        System.Diagnostics.Debug.WriteLine(format, args);    #endif        Console.WriteLine(format, args);    }    public void I(string format, params object[] args)  //InfoCut off if not talkative.    {        if (_Talk)            W(format, args);    }}
Archiving files into directories
c#;file