2017-06-11 4 views
0

基本的に私のコードをバッチファイル(.bat)からC#コンソールアプリケーションに移行しようとしています。私はVisual C#2010 Expressを使用しています。プライマリ機能は、コマンドラインユーティリティのホスト用のTUIベースのアシスタントです。私の問題は単純でなければならない。しかし私はそれだけで解決することができませんでした。C# - 特定のファイルタイプのディレクトリを列挙し、ループ内の各ファイルを使用します。

特定の拡張子のファイルごとにディレクトリを列挙しようとしています。パスを保存している間に、現在のファイルのファイル名は&の変数になります。その後、個々のファイルごとにその情報をcmd.exeに送信します。しかし、私はそれを正しくループする方法を理解することはできません。私がすでに持っているコードは正しいとは思わない。

@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#でこの部分を持っている何を:私は再現するのに苦労していますセクションから[]

例可能System.String

string patches = Directory.GetFiles(pathDir, "*.patch");戻り

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

あなたはあなたのためにできることを忘れてしまった! cmdプロセスを開始するために、ディレクトリサービスについて、ファイルクラスについてなど、あなたは強力なツールを親指で利用しています。それらを使用してください。 – elzooilogico

+0

@elzooilogico踏み石、私はそこに着くでしょう。私は大したことを忘れてしまった。これは、主にtk/tclに焦点を当てたFreeBSDおよびOS Xに変換して放棄した古いプロジェクトです。 Windowsから永遠に実行することはできません。 – Terus

+0

すべての機能を有効にして、より良い理解を得ました。意図的にコードを壊してそこに到着しました。しかし、私は今、何が起こっているかをしっかりと把握しています。両方の答えは素晴らしかったし、私は両者がなければ私が現在持っている洞察を得ていないだろう。私はしかし、私の仕事で良い医師の例を実装している。私はそれを「正しい」答えと記しています。もう一度、ありがとう。私はいくつかの本を手に入れ、C#をより深く学ぶ必要があります。 – Terus

答えて

1

私はバッチファイルでは大したことではありませんが、C#に慣れています。このプログラムでは、のすべてのパスがpathDirにあり、各ファイルパスごとにコマンド文字列が作成され、コマンドで新しい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%確信していません。


ドクター・フィールグッドの応答から、これは異なる作ることを指摘しておきいくつかのポイント:

  • GetFilesが配列を返すので、Listに変換する必要はありません。 .NET Listは、基本的に、コレクションのサイズ変更を可能にするArrayのラッパーです。
  • Directory.GetFilesは、FileInfoオブジェクトを返すDirectoryInfo.GetFilesではなく、パス文字列の配列を返します。 Directoryはディレクトリを操作する静的クラスですが、DirectoryInfoはインスタンスクラスで、各インスタンスは1つのディレクトリを表します。
  • DirectoryInfo/FileInfoを使用している場合、最終的には文字列に変換されるため、個々のオブジェクトを作成して各ファイルの詳細をカプセル化する必要はありません。 (FileInfoも既に同じ抽象化されています)。文字列に変換する方が効率的です。
  • Selectメソッドは、レイジーシーケンスであるIEnumerable<T>を返します。つまり、すべてのファイルパスが即座にフォーマットされた文字列に変換されず、シーケンスがforeachループで消費されるときに1つずつフォーマットされます。あなたのコレクションが小さい(おそらく500アイテム未満)場合、違いは見えないかもしれませんが、それが大きい場合は時間を節約できます。
  • ストレートforeachループにSelectによって作成されたIEnumerableを供給すること、別のList(前の回答でdata)の作成を避けることができます。
+0

これは、彼がC#の方が新しいと言っているOPの記述の通りです。将来のために留意すべき点は、この時点で彼が理解するのが簡単かもしれません。 –

+0

@JamesFaix まずはお返事ありがとうございます。これは洗練された解決策です。残念ながら、私はそれを完全には理解していません。コンパイラエラーもあります。 25行目は「 'char'から 'string'に変換できません。私のバージョンのVisual C#は、日付が付いているかもしれません。 Visual C#ExpressはVisual C#Communityになっています。ダミーのファイル/フォルダの設定があります。だから私はちょうどテストするために直接コピー/ペーストをしました。 – Terus

+0

@Dr_FeelGood確かに、私はC#の少し新しいです。特にWindows環境でファイルシステムを扱う場合。私のC#の知識の大部分は、OS XのUnity3DのMonoからのものです。 – 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. 
    } 
} 

編集:さらに、次のようなファイル情報にアクセスして、それぞれを反復することができます。

+0

ご回答いただきありがとうございます。これはかなり正直なようです。従うのが比較的簡単です。ちょうどそれにテストを与えること。 – Terus

+1

問題はありません。詳しい説明が必要な場合はお知らせください。回答を更新できます。 JamesFaixのポイントは、ファイルの範囲がどれだけ大きいかによって、繰り返し進むことになります。これは、あなたが理解し、あなたが行くにつれてそれをより効率的にするのを助けるのに、確かに良い出発点です。 –

関連する問題