5

dwg ファイルでいっぱいのフォルダーがあるので、ファイルの最新バージョンを見つけるか、ファイルにバージョンがない場合はそれをディレクトリにコピーするだけです。たとえば、次の 3 つのファイルがあります。

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

違いは、あるファイルには があり_1、別のファイルには がある_2ことに注意してください。したがって、ここの最新のファイルは_2. 最新のファイルを保持し、ディレクトリにコピーする必要があります。一部のファイルには異なるバージョンがないため、コピーできます。多くの場合、それらは同じであるため、ファイルの作成日または変更日に焦点を当てることはできず、ファイル名自体を確認するだけです。これを行うには、以下に投稿する方法よりも効率的な方法があると確信しています。

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;
    }
}
4

5 に答える 5

1

Enumerable.GroupBy 動作するはずのこのLinqクエリを使用できます(現在テスト済み):

var allFiles = Directory.EnumerateFiles(sourceDir, "*.dwg")
    .Select(path => new
    {
        Path = path,
        FileName = Path.GetFileName(path),
        FileNameWithoutExtension = Path.GetFileNameWithoutExtension(path),
        VersionStartIndex = Path.GetFileNameWithoutExtension(path).LastIndexOf('_')
    })
    .Select(x => new
    {
        x.Path,
        x.FileName,
        IsVersionFile = x.VersionStartIndex != -1,
        Version = x.VersionStartIndex == -1 ? new Nullable<int>()
            : x.FileNameWithoutExtension.Substring(x.VersionStartIndex + 1).TryGetInt(),
        NameWithoutVersion = x.VersionStartIndex == -1 ? x.FileName
            : x.FileName.Substring(0, x.VersionStartIndex)
    })
    .OrderByDescending(x => x.Version)
    .GroupBy(x => x.NameWithoutVersion)
    .Select(g => g.First());

foreach (var file in allFiles)
{
    string oldPath = Path.Combine(sourceDir, file.FileName);
    string newPath;
    if (file.IsVersionFile && file.Version.HasValue)
        newPath = Path.Combine(versionPath, file.FileName);
    else
        newPath = Path.Combine(noVersionPath, file.FileName);
    File.Copy(oldPath, newPath, true);
}

astringが解析可能かどうかを判断するために使用している拡張メソッドは次のintとおりです。

public static int? TryGetInt(this string item)
{
    int i;
    bool success = int.TryParse(item, out i);
    return success ? (int?)i : (int?)null;
}

私は正規表現ではなく文字列メソッドのみを使用していることに注意してください。

于 2013-01-30T14:07:06.617 に答える
1

私は正規表現ベースのソリューションを作成しましたが、その間にパーティーに遅れてきたようです。

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

この正規表現は、ファイル名とバージョンを認識し、それらをグループに分割します。非常に単純な foreach ループで、辞書内の最新のファイルを取得します (私は怠け者なので)。アクセスする前に、ファイル名を再度まとめる必要があります。彼ら。

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

完全なコード

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" );
    // ...
}
于 2013-01-30T14:25:55.173 に答える
0

これは、fileList にすべてのファイル名が含まれていることを考慮して、必要なものです。

List<string> latestFiles=new List<string>();
foreach(var groups in fileList.GroupBy(x=>Regex.Replace(x,@"(_\d+\.dwg$|\.dwg$)","")))
    {
        latestFiles.Add(groups.OrderBy(s=>Regex.Match(s,@"\d+(?=\.dwg$)").Value==""?0:int.Parse(Regex.Match(s,@"\d+(?=\.dwg$)").Value)).Last());
    }

latestFiles には、すべての新しいファイルのリストがあります。

fileList が大きい場合は、Threadingまたはを使用します。PLinq

于 2013-01-30T15:07:41.780 に答える
0

これを試して

var files = new My.Computer().FileSystem.GetFiles(@"c:\to\the\sample\directory", Microsoft.VisualBasic.FileIO.SearchOption.SearchAllSubDirectories, "*.dwg");
foreach (String f in files) {
    Console.WriteLine(f);
};

注意:Microsoft.VisualBasicクラスの先頭に次の行への参照を追加して

using My = Microsoft.VisualBasic.Devices;

アップデート

作業サンプル[テスト済み]:

String dPath=@"C:\to\the\sample\directory";
var xfiles = new My.Computer().FileSystem.GetFiles(dPath, Microsoft.VisualBasic.FileIO.SearchOption.SearchAllSubDirectories, "*.dwg").Where(c => Regex.IsMatch(c,@"\d{3,}\.dwg$"));
XElement filez = new XElement("filez");
foreach (String f in xfiles)
{
    var yfiles = new My.Computer().FileSystem.GetFiles(dPath, Microsoft.VisualBasic.FileIO.SearchOption.SearchAllSubDirectories, string.Format("{0}*.dwg",System.IO.Path.GetFileNameWithoutExtension(f))).Where(c => Regex.IsMatch(c, @"_\d+\.dwg$"));
    if (yfiles.Count() > 0)
    {
        filez.Add(new XElement("file", yfiles.Last()));            
    }
    else {
        filez.Add(new XElement("file", f));
    };
};
Console.Write(filez);
于 2013-01-30T13:54:38.113 に答える
0

文字列ソートでこれを行うことはできますか?ここで唯一難しいのは、ファイル名をソート可能な形式に変換することです。文字列を dd-mm-yyyy から yyyymmdd に置換するだけです。次に、リストをソートして最後のレコードを取得します。

于 2013-01-30T14:32:01.583 に答える