2017-06-11 41 views
0

本質上,我試圖將我的代碼從批處理文件(.bat)遷移到C#控制檯應用程序。我正在使用Visual C#2010 Express。主要功能是許多命令行實用程序的基於TUI的助手。我的問題應該很簡單。但是我一直無法單獨解決它。C# - 枚舉特定文件類型的目錄,然後在循環中使用每個文件

我一直在試圖枚舉某個擴展類型的每個文件的目錄。在存儲路徑時,文件名&將當前文件擴展名到一個變量中。然後將該信息發送到每個單獨文件的cmd.exe。但我不知道如何正確地循環它。我也不認爲我已經擁有的代碼是正確的。

string patches = Directory.GetFiles(pathDir, "*.patch");返回System.String []從我掙扎的部分

實施例重現:

@echo off 
SETLOCAL EnableDelayedExpansion 

:: Variables hardcoded for the sake of example. 

:: Folder containing patches 
set "pathDir=C:\Main\Directory\Path\External" 
:: File to apply patches on 
set "varFile=C:\Main\Directory\Path\file.tmp" 
:: Utility that applies patches 
set "progExt=C:\Main\Directory\Path\Program.exe" 
cls 

:: Main loop 
For /F "delims=" %%A In (' DIR /B /O:N /A:-D "%pathDir%\*.patch" ') Do (
    :: Announce current filename 
    echo Patching %%A 
    :: Any key to contine - Makeshift confirmation without cancel 
    pause 
    :: Arguments to invoke external application 
    "%progExt%" "%pathDir%\%%A" "%varFile%" 
:: End Loop 
) 
cls 

我有什麼這部分在C#迄今:

string pathDir = @"C:\Main\Directory\Path\External"; 
string varFile = @"C:\Main\Directory\Path\file.tmp"; 
string progExt = @"C:\Main\Directory\Path\Program.exe"; 
string patches = Directory.GetFiles(@pathDir, "*.patch"); 
// Set variable for current file - Missing 
string cmdDebug = "/C echo "; // enable with IF statements later 
System.Diagnostics.Process.Start("CMD.exe", cmdDebug + pathDir + "&& echo " + varFile + "&& echo " + progExt + "&& echo " + patches + "&& pause"); 
// System.Diagnostics.Process.Start("CMD.exe","/C " + progExt + " " + curPatch + " " + varFile"; 

這些是我的包括:

using System; 
using System.IO; 
using System.Linq; 
using System.Text; 
using System.Diagnostics; 
using System.Collections.Generic; 
+0

恕我直言,你已經忘記了c#能爲你做些什麼!你正在用它來啓動一個cmd進程,目錄服務怎麼樣,關於文件類等,你有你的拇指下的強大工具。使用它們。 – elzooilogico

+0

@elzooilogico墊腳石,我會到那裏。我忘記了很多。這是一箇舊的項目,我轉換到FreeBSD&OS X後主要集中在tk/tcl。儘管如此,仍然無法從Windows運行。 – Terus

+0

得到了一切工作,並獲得了更好的理解。花了很多故意破壞代碼到達那裏。但是我現在已經牢牢掌握了發生了什麼事情。兩個答案都很棒,如果沒有這兩個,我就不會獲得我現在擁有的洞察力。然而,我在我的工作中實施了良好的醫生榜樣。因此,我已經將此標記爲「正確」的答案。再次感謝你們。我需要拿起一些書並深入學習C#。 – Terus

回答

1

我對批處理文件不太好,但流利的C#。該程序將找到pathDir中所有.patch文件的路徑,然後爲每個文件創建一個用於每個文件路徑的命令字符串,並使用該命令啓動一個新的CMD進程。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Diagnostics; 
using System.IO; 

static class Program { 

    static void Main() 
    { 
     var pathDir = @"C:\Main\Directory\Path\External"; 
     var varFile = @"C:\Main\Directory\Path\file.tmp"; 
     var progExt = @"C:\Main\Directory\Path\Program.exe"; 

     var commandBase = string.Format("/C echo {0} && echo {1} && echo {2} && echo ", 
      pathDir, varFile, progExt); 

     var commands = Directory 
      .GetFiles(@pathDir, "*.patch") 
      .Select(file => string.Format("{0}{1}&& pause", commandBase, file)); 

     foreach (var c in commands){ 
      Process.Start("CMD.exe", c); 
     } 
    } 
} 

我不是100%確定它匹配原始文件的邏輯。


值得指出的幾點,使從FEELGOOD博士的迴應此不同:

  • 由於GetFiles返回一個數組,就沒有必要轉換爲List。 .NET List基本上是Array的包裝,允許調整集合的大小。
  • Directory.GetFiles返回一組路徑字符串,而不是DirectoryInfo.GetFiles,它返回FileInfo對象。 Directory是一個用於操作目錄的靜態類,而DirectoryInfo是一個實例類,其中每個實例表示一個目錄。
  • 如果使用DirectoryInfo/FileInfo,則不需要創建單個對象來封裝每個文件的詳細信息,因爲它們最終只是變成了字符串。 (另外,FileInfo已經是相同的抽象。)將直接轉換爲字符串更有效。
  • Select方法返回一個IEnumerable<T>這是一個惰性序列,這意味着所有文件路徑都不會立即轉換爲格式化的字符串,因爲該序列被foreach循環佔用,所以它們一次格式化一次。如果您的收藏品很小(可能少於500件),您可能看不到差異,但如果它很大,則可以節省時間。
  • 將由Select創建的IEnumerable直接送入foreach循環避免了在上一個答案中創建另一個Listdata)。
+0

這只是解釋/闡述,因爲OP聲明他更新C#。雖然對未來有好處,但在這個時間點他可能會更容易理解。 –

+0

@JamesFaix 首先非常感謝你的迴應。這似乎是一個優雅的解決方不幸的是我並不完全理解它。還有一個編譯器錯誤。第25行指出「不能從'char'轉換爲'string'」。我的Visual C#版本可能會過時。我看到Visual C#Express現在是Visual C#社區。我有虛擬文件/文件夾設置。所以我只是做了一個直接的複製/粘貼來測試。 – Terus

+0

@Dr_FeelGood事實上,我對C#有點新鮮。特別是在Windows環境中並處理文件系統。我的C#知識大部分來自Unity3D中的Mono,在OS X下。 – Terus

1

嘗試像下面的東西,看看是否適用於你。

private void GetFiles() 
{ 
    DirectoryInfo DIRINF = new DirectoryInfo("C:\\STAIRWAYTOHEAVEN"); 
    List<FileInfo> FINFO = DIRINF.GetFiles("*.extension").ToList(); 
    List<object> Data = new List<object>(); 
    foreach (FileInfo FoundFile in FINFO) 
    { 
     // do somthing neat here. 
     var Name = FoundFile.Name; // Gets the name, MasterPlan.docx 
     var Path = FoundFile.FullName; // Gets the full path C:\STAIRWAYTOHEAVE\GODSBACKUPPLANS\MasterPlan.docx 
     var Extension = FoundFile.Extension; // Gets the extension .docx 
     var Length = FoundFile.Length; // Used to get the file size in bytes, divide by the appropriate number to get actual size. 

     // Make it into an object to store it into a list! 
     var Item = new { Name = FoundFile.Name, Path = FoundFile.FullName, Size = FoundFile.Length, Extension = FoundFile.Extension }; 
     Data.Add(Item); // Store the item for use outside the loop. 
    } 
} 

編輯:爲了進一步提高您的瀏覽效果,您可以像下面這樣訪問文件信息,以便遍歷每個文件。

foreach (dynamic Obj in Data) // Access the properties via a dymanic object so there isn't a huge conversion process with propertyinfo 
    { 
     System.Diagnostics.Process.Start("cmd.exe", "/c echo " + Path.GetDirectoryName(Obj.FullName) + "&& echo ....."); 
    } 
+0

非常感謝您的回覆。這看起來很直截了當。相對容易遵循。正要給它一個測試。 – Terus

+1

沒問題,讓我知道如果你需要進一步的解釋,我可以更新答案。記住JamesFaix的觀點,這取決於您打算遍歷的文件範圍有多大。這是一個很好的起點,但可以幫助您瞭解並提高效率。 –

相關問題