Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find the Filename with the latest version in C#

I have a folder that is filled with dwg files so I just need to find the latest version of a File or if a File has no versions then copy it to a directory. For example here are three files:

ABBIE 08-10 #6-09H4 FINAL 06-12-2012.dwg
ABBIE 08-10 #6-09H4 FINAL 06-12-2012_1.dwg
ABBIE 08-10 #6-09H4 FINAL 06-12-2012_2.dwg

Notice the difference is one file has a _1 and another has a _2 so the latest file here is the _2. I need to keep the latest file and copy it to a directory. Some files will not have different versions so those can be copied. I cannot focus on the creation date of the file or the modified date because in many instances they are the same so all I have to go on is the file name itself. I'm sure there is a more efficient way to do this than what I will post below.

DirectoryInfo myDir = new DirectoryInfo(@"H:\Temp\Test");
var Files = myDir.GetFiles("*.dwg");

string[] fileList = Directory.GetFiles(@"H:\Temp\Test", "*FINAL*", SearchOption.AllDirectories);

ArrayList list = new ArrayList();
ArrayList WithUnderscores = new ArrayList();
string nameNOunderscores = "";

for (int i = 0; i < fileList.Length; i++)
{
    //Try to get just the filename..
    string filename = fileList[i].Split('.')[0];
    int position = filename.LastIndexOf('\\');
    filename = filename.Substring(position + 1);
    filename = filename.Split('_')[0];

    foreach (FileInfo allfiles in Files)
    {
        var withoutunderscore = allfiles.Name.Split('_')[0];
        withoutunderscore = withoutunderscore.Split('.')[0];
        if (withoutunderscore.Equals(filename))
        {
            nameNOunderscores = filename;
            list.Add(allfiles.Name);
        }
    }

    //If there is a number after the _ then capture it in an ArrayList
    if (list.Count > 0)
    {
        foreach (string nam in list)
        {
            if (nam.Contains("_"))
            {
                //need regex to grab numeric value after _
                var match = new Regex("_(?<number>[0-9]+)").Match(nam);
                if (match.Success)
                {
                    var value = match.Groups["number"].Value;
                    var number = Int32.Parse(value);

                    WithUnderscores.Add(number);
                }
            }
        }

        int removedcount = 0;

        //Whats the max value?
        if (WithUnderscores.Count > 0)
        {
            var maxval = GetMaxValue(WithUnderscores);
            Int32 intmax = Convert.ToInt32(maxval);

            foreach (FileInfo deletefile in Files)
            {
                string shorten = deletefile.Name.Split('.')[0];
                shorten = shorten.Split('_')[0];
                if (shorten == nameNOunderscores && deletefile.Name != nameNOunderscores + "_" + intmax + ".dwg")  
                {
                    //Keep track of count of Files that are no good to us so we can iterate to next set of files
                    removedcount = removedcount + 1;

                }
                else
                {
                    //Copy the "Good" file to a seperate directory
                    File.Copy(@"H:\Temp\Test\" + deletefile.Name, @"H:\Temp\AllFinals\" + deletefile.Name, true); 
                }
            }

            WithUnderscores.Clear();
            list.Clear();
        }

        i = i + removedcount;
    }
    else
    {
        //This File had no versions so it is good to be copied to the "Good" directory
        File.Copy(@"H:\Temp\SH_Plats\" + filename, @"H:\Temp\AllFinals" + filename, true);
        i = i + 1;
    }
}
like image 961
DaBears Avatar asked Nov 04 '22 05:11

DaBears


1 Answers

I've made a Regex based solution, and apparently come late to the party in the meantime.

(?<fileName>[A-Za-z0-9-# ]*)_?(?<version>[0-9]+)?\.dwg

this regex will recognise the fileName and version and split them into groups, a pretty simple foreach loop to get the most recent files in a dictionary (cos I'm lazy) and then you just need to put the fileNames back together again before you access them.

var fileName = file.Key + "_" + file.Value + ".dwg"

full code

var files = new[] {
    "ABBIE 08-10 #6-09H4 FINAL 06-12-2012.dwg",
    "ABBIE 08-10 #6-09H4 FINAL 06-12-2012_1.dwg",
    "ABBIE 08-10 #6-09H4 FINAL 06-12-2012_2.dwg",
    "Second File.dwg",
    "Second File_1.dwg",
    "Third File.dwg"
};

// regex to split fileName from version
var r = new Regex( @"(?<fileName>[A-Za-z0-9-# ]*)_?(?<version>[0-9]+)?\.dwg" );
var latestFiles = new Dictionary<string, int>();

foreach (var f in files)
{
    var parsedFileName = r.Match( f );
    var fileName = parsedFileName.Groups["fileName"].Value; 
    var version = parsedFileName.Groups["version"].Success ? int.Parse( parsedFileName.Groups["version"].Value ) : 0;

    if( latestFiles.ContainsKey( fileName ) && version > latestFiles[fileName] )
    {
        // replace if this file has a newer version
        latestFiles[fileName] = version;
    }
    else
    {
        // add all newly found filenames
        latestFiles.Add( fileName, version );
    }
}

// open all most recent files
foreach (var file in latestFiles)
{
    var fileToCopy = File.Open( file.Key + "_" + file.Value + ".dwg" );
    // ...
}
like image 126
Dead.Rabit Avatar answered Nov 09 '22 11:11

Dead.Rabit