concurve
Goto Top

Ordner durchsuchen - wenn "bestimmter Text" in einer Datei enthalten, diese Datei in einen anderen Ordner kopieren oder verschieben

Hallo zusammen,

ich habe ein Problem bei der Erstellung einer *.bat, welche innerhalb eines zu definierenden Ordners alle Dateien nach einer bestimmten "Begrifflichkeit" (so z.B. "Fehler XY an TXVcs2") durchsuchen soll. Die zu durchsuchende Datei hat die Dateiendung=*.MSG, diese kann jedeoch z.B. mit dem Editor regulär gelesen werden.
Wird die *.bat fündig, so soll die *.MSG in ein zu definierendes Verzeichnis kopiert/verschoben werden.


Dieses Code hier habe ich im Netz gefunden ...
Find /i "FEHLER" Update_AV_log.txt  
if errorlevel 1 goto notfound
copy F:\Update_AV_log.txt "C:\Dokumente und Einstellungen\Plancad-SK\Desktop\Update_AV_log_copy.txt"  
REN "C:\Dokumente und Einstellungen\Plancad-SK\Desktop\Update_AV_log_copy.txt" AV_%date%.txt  
:notfound

... und ihn entsprechend auf meine Bedürfnisse abgeändert ...

set root=%~dp0
set MSGunpacked=%~dp0TYP_LOGS\entpackt\
set MSGneed=%~dp0TYP_LOGS\zu_verwenden\
set mydate=%date:~-4%-%date:~-7,2%-%date:~-10,2%

md TYP_LOGS\zu_verwenden\%mydate%

Find /i "Fehler XY an TXVcs2!" "%MSGunpacked%*.MSG"  
if errorlevel 1 goto notfound
copy "%MSGunpacked%*.MSG" "%MSGneed%\%mydate%\*.MSG"  
:notfound

pause

An verschiedenen Stellen habe ich nun auch schon Änderungen im Code vorgenommen aber was ich auch mache ... die *.bat arbeitet nicht und mir fehlt leider die Kenntnis um die Ursache dafür ausfindig zu machen.

Wäre toll wenn mir hier jemand helfen könnte.

Gruß
Con

Content-ID: 320511

Url: https://administrator.de/contentid/320511

Ausgedruckt am: 22.11.2024 um 05:11 Uhr

TlBERlUS
TlBERlUS 10.11.2016 aktualisiert um 11:04:09 Uhr
Goto Top
Moin.

"...arbeitet nicht..." ist im Zweifel nicht hilfreich...

Powershell:
clear-host

$source = ".\Desktop\test"  
$destination = ".\Desktop\ziel"  

$files = gci $source

foreach ($f in $files){
    $match = $false
    $content = gc $source\$f
    foreach ($c in $content){
        switch($c){
            "Fehler XY an TXVcs2"{$match = $true}  
        }
    }
    if ($match -eq $true){
        Move-Item $source\$f -Destination $destination
    }
}

Grüße,

Tiberius
Concurve
Concurve 10.11.2016 um 13:02:04 Uhr
Goto Top
Hallo Tiberius und besten Dank!

Ich habe mir eine *.bat erstellt, die dann die *.ps1 ausführt (ich hatte bis dato noch nix mit Powershell zu tun und hatte erstmal Schwierigkeiten beim "Starten".

@echo on
Powershell.exe -executionpolicy remotesigned -File X:\X2Z\TYP_Daten_CS\MSG_BR.ps1
pause


Hier aber nun Dein Code, mit dem ich bedauerlicherweise auch so meine Schwierigkeiten habe ... mein CMD bleibt nach der *.bat, also wenn dann die *.ps1 ausgeführt wird schwarz

clear-host

$source = "X:\X2Z\TYP_Daten_CS\TYP_LOGS\entpackt"  
$destination = "X:\AK0\TYP_Daten_CS\TYP_LOGS\zu_verwenden"  

$files = gci $source

foreach ($f in $files){
    $match = $false
    $content = gc $source\$f
    foreach ($c in $content){
        switch($c){
            "10314973.28T 10314973.28T"{$match = $true}  
        }
    }
    if ($match -eq $true){
        Move-Item $source\$f -Destination $destination
    }
}

Habe ich ggf. einen Fehler bei meinen Pfaden? Ich habe verschiedene Schreibweisen versucht (was man halt im Netz so dazu findet) aber an dem oben beschriebenen Problem ändert sich nichts (außer ich nehme die " weg, dann durchläuft die Suche den Ordner, in der die *.ps1 liegt).

Um Hilfe bin ich dankbar.

Gruß
Con
TlBERlUS
TlBERlUS 10.11.2016 um 13:45:18 Uhr
Goto Top
Zitat von @Concurve:

Hallo Tiberius und besten Dank!
Kein Problem
Ich habe mir eine *.bat erstellt, die dann die *.ps1 ausführt (ich hatte bis dato noch nix mit Powershell zu tun und hatte erstmal Schwierigkeiten beim "Starten".
Warum den über Batch/CMD? Das ist veraltete Technik. Wenn du WIn7 oder höher hast, führe die Powershell doch direct aus.
um das ganze übersichtlicher zu machen
C:\windows\system32\WindowsPowerShell\v1.0\powershell_ise.exe (das ist quasi die Entwicklerumgebung)
Hier aber nun Dein Code, mit dem ich bedauerlicherweise auch so meine Schwierigkeiten habe ... mein CMD bleibt nach der *.bat, also wenn dann die *.ps1 ausgeführt wird schwarz
In der cmd gibt es nur eine Ausgabe, wenn die cmd etwas macht. Das ist hier aber nicht der Fall, da darüber nur die Powershell gestartet wird.
> clear-host
> 
> $source = "X:\X2Z\TYP_Daten_CS\TYP_LOGS\entpackt"  
> $destination = "X:\AK0\TYP_Daten_CS\TYP_LOGS\zu_verwenden"  
> 
> $files = gci $source
> 
> foreach ($f in $files){
>     $match = $false
>     $content = gc $source\$f
>     foreach ($c in $content){
>         switch($c){
>             "10314973.28T 10314973.28T"{$match = $true}  
>         }
>     }
>     if ($match -eq $true){
>         Move-Item $source\$f -Destination $destination
>     }
> }
> 
Code sieht erstmal in Ordnung aus (btw. Unterordner werden nicht durchsucht.)
Concurve
Concurve 10.11.2016 um 14:32:20 Uhr
Goto Top
Ich habe nun direkt den Quellcode in die PowerShell-Eingabemaske kopiert (1:1) ... soweit läuft alles und es wird mir sodann auch als "Completed" angezeigt (nach ein paar Minuten, sind ja einige Datensätze).

Bei meinen Daten hat sich jedoch nichts getan - sprich es wurde nichts verschoben oder kopiert. Selbst wenn ich einen Wert als "Suchbegriff" eintrage der in jeder Datei vorkommt, macht mein Rechner hier nichts.

Ich habe nun mal aus einer *.MSG ein *.txt gemacht und dann nach einem Text gesucht der in der *.txt steht ...

Eine Zeile aus meiner *.txt:
167401 008102 shell(@?) del XKp/tres.ini (Dir=WPRAM/ZGFNTFMT)

Suchbegriff: ZGFNTFMT

... auch hier ist nichts passiert.

Mache ich da etwas grundlegendes falsch oder hängt das ggf. mit Benutzerrechten zusammen?!

Gruß
Con
colinardo
colinardo 10.11.2016 aktualisiert um 17:53:55 Uhr
Goto Top
Hallo Con,
Ich habe nun mal aus einer *.MSG ein *.txt gemacht und dann nach einem Text gesucht der in der *.txt steht ...
der Grund ist das RAW ausgelesen die Strings in Unicode anders kodiert sind. In der Textdatei sieht das zwar so aus, dem ist aber nicht so (Öffne die Datei mal im Hexeditor dann siehst du es). Deswegen empfehle ich dir den Inhalt der Mail zuverlässiger gleich über das Outlook-Com-Object auszulesen, damit kommst du an den Plaintextinhalt der Mail.

Beispiel wenn der gesuchte String im Body der Mail vorkommt:
$objOL = new-object -Com Outlook.Application
$searchstring = 'ZGFNTFMT'  
$source = 'C:\quelle'  
$destination = 'C:\ziel'  
gci $source -Filter *.msg -recurse | %{
    $mail = $objOL.CreateItemFromTemplate($_.Fullname)
    if ($mail.Body -like "*$searchstring*"){  
         $_ | move-item -Destination $destination -Force -Verbose
    }
    $mail.Close(1)
}
Du kannst auch andere Teile der Nachricht durchsuchen, das kann man nach Belieben anpassen.

Das Outlook auf dem Rechner auf dem das Script ausgeführt wird, vorhanden sein muss, ist für das obige Script Voraussetzung.


Falls das nicht in Frage kommt und die MSG-Files einheitlich in Unicode vorliegen dann geht's auch ohne so als Einzeiler wenn man die Variablendefrinitionen der Übersicht halber abzieht.
$searchstring = 'deinsuchstring'  
$source = 'C:\quelle'  
$destination = 'C:\ziel'  
gci $source -Filter *.msg -recurse | ?{(gc $_.Fullname -Encoding Unicode | out-string) -like "*$searchstring*" } | move-item -Destination $destination -force -verbose  

Grüße Uwe
Concurve
Concurve 11.11.2016 um 10:18:47 Uhr
Goto Top
Hallo Uwe, und vielen Dank für die Erklärung (ich habe mir das File im Hexeditor angesehen und ja, es sieht in der Tat "etwas" anders aus ... auch wenn ich davon 0 verstehe face-wink ).

Deinen ersten Code habe ich nun in PowerShell direkt einkopiert und habe folgendes Ergebnis erhalten:

Die Datei 'C:\Users\XK8j5\Desktop\TYP_LOGS\entpackt\74652876_2016-11.MSG' kann nicht geöffnet werden. Möglicherweise ist die Datei   
bereits geöffnet, oder Sie sind nicht berechtigt, die Datei zu öffnen.

Klicken Sie mit der rechten Maustaste auf den Dateiordner, und klicken Sie dann auf 'Eigenschaften', um Ihre Berechtigungen zu überprüfen.  
At line:8 char:5
+     $mail = $objOL.CreateItemFromTemplate($_.Fullname)
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (:) , COMException
    + FullyQualifiedErrorId : System.Runtime.InteropServices.COMException
 
You cannot call a method on a null-valued expression.
At line:12 char:5
+     $mail.Close(1)
+     ~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) , RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

Diese Meldung habe ich nun 5.879 mal (je Datensatz) ... irgendwas scheint das also nicht ganz zu passen.

Und auf "C:" sollte ich ja nun voll zugreifen können oder kann die EDV da ggf. etwas limitiert haben? Installationen von Programmen etc. kann ich ohne weiteres Lokal durchführen.

Gruß
Con
colinardo
colinardo 11.11.2016 um 10:26:49 Uhr
Goto Top
Deinen ersten Code habe ich nun in PowerShell direkt einkopiert und habe folgendes Ergebnis erhalten:
Falsch, mach daraus ein Skript und führe es dann aus!
Wurde hier einwandfrei mit 500 Testmails im *.msg Format getestet. Es liegt also an deiner Umgebung.
Concurve
Concurve 11.11.2016 um 11:29:17 Uhr
Goto Top
Hallo Colinardo,

ich habe nun über "regedit" PowerShell auf "Unrestricted" gesetzt ... hier ein entsprechender Auszug von der Gegenkontrolle:
[DBG]: PS C:\Users\XK8j5\Desktop\TYP_LOGS>> Get-ExecutionPolicy
Unrestricted


Dann habe ich mein *.ps1 gestartet:
[DBG]: PS C:\Users\XK8j5\Desktop\TYP_LOGS>> . C:\Users\XK8j5\Desktop\TYP_LOGS\test.ps1

Und dann "n" mal diese Meldung hier erhalten (ich habe dann abgebrochen):

Die Datei 'C:\Users\XK8j5\Desktop\TYP_LOGS\entpackt\74652876_2016-11.MSG' kann nicht geöffnet werden. Möglicherweise ist die Datei   
bereits geöffnet, oder Sie sind nicht berechtigt, die Datei zu öffnen.

Klicken Sie mit der rechten Maustaste auf den Dateiordner, und klicken Sie dann auf 'Eigenschaften', um Ihre Berechtigungen zu überprüfen.  
At C:\Users\XK8j5\Desktop\TYP_LOGS\test.ps1:8 char:5
+     $mail = $objOL.CreateItemFromTemplate($_.Fullname)
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (:) , COMException
    + FullyQualifiedErrorId : System.Runtime.InteropServices.COMException
 
You cannot call a method on a null-valued expression.
At C:\Users\XK8j5\Desktop\TYP_LOGS\test.ps1:12 char:5
+     $mail.Close(1)
+     ~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) , RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull
 

Hast Du noch eine Idee an was es liegen kann ... muss mich vielleicht die EDV für PowerShell "freischalten"?

Gruß
Con
colinardo
colinardo 11.11.2016 aktualisiert um 11:55:45 Uhr
Goto Top
Ich vermute dein Outlook wurde hier in irgendeiner Art und Weise beschränkt oder die Berechtigungen auf der Quelle sind zu restriktiv übernommen worden.
Nimm mal einen unbeschränkten Rechner dann wirst du sehen das es läuft.
Alternativ nimm Variante 2 von oben die sollte dir auch reichen.
Concurve
Concurve 15.11.2016 um 04:40:19 Uhr
Goto Top
Hallo Colinardo,

nach dem Test an meinem PC (privat) habe ich bedauerlicherweise gleiches Problem wie auch schon zuvor. Hier nun meine Vermutung hinsichtlich der Daten ...

-ich bin mir nicht sicher ob meine *.MSG-Dateien auch tatsächlich Outlook-Elemente sind oder ob die nicht nur mit dieser Dateiendung gespeichert wurden (In Outlook kann ich die nämlich nicht öffnen - gleiche Fehlermeldung wie in Powershell "Die Datei 'C:\....MSG' kann nicht geöffnet werden ... Datei bereits geöffnet, ... nicht berechtigt, die Datei zu öffnen.")?!

Wie könnte ich denn z.B. eine "normale" Textdatei nach bestimmten Wörtern durchsuchen (analog der obigen Anfrage), dann würde ich das einfach mal versuchen. Den Code von Tiberius habe ich bereits ausprobiert, damit hat es nur leider nicht funktioniert.

Gruß
Con
colinardo
colinardo 15.11.2016 aktualisiert um 09:47:35 Uhr
Goto Top
Ich wiederhole mich, siehe meine zweite Lösung in meinem ersten Beitrag oben! Ansonsten eine MSG Datei von dir hochladen damit wir wissen was Sache ist und welche Kodierung die Strings aufweisen, Danke.
Concurve
Concurve 19.11.2016 um 07:31:19 Uhr
Goto Top
Hallo noch einmal,

nun habe ich in den vergangenen Tagen diverse Versuche an drei verschiedenen PC's (1xArbeit/2xPrivat) durchgeführt und komme zu folgendem Ergebnis:

Test-Dateien:
- Die von Anfang an benannten *.MSG-Dateien
(hier bin ich aber nicht sicher ob es tatsächlich Outlook-Elemente sind, vielmehr glaube ich, dass es normale Textdateien sind).
- Eine "richtige" E-Mail aus Outlook mit dem Textinhalt "Anfrage"
- Eine *.txt (Textdokument1.txt) mit dem folgendem Inhalt (Zeile1: eine Anfrage10310668)
- Eine *.txt (Textdokument2.txt) mit dem folgendem Inhalt (Zeile1: eine Axxnfrage; Zeile 2: 10310668)

Szenario 1:
$objOL = new-object -Com Outlook.Application
$searchstring = 'Anfrage'  
$source = 'C:\xxx'  
$destination = 'C:\xxx'  
gci $source -Filter *.MSG -recurse | %{
    $mail = $objOL.CreateItemFromTemplate($_.Fullname)
    if ($mail.Body -like "*$searchstring*"){  
         $_ | move-item -Destination $destination -Force -Verbose
    }
    $mail.Close(1)
}

"Anfrage" *.* = alles wurde kopiert (Fehler)
"Anf rage" *.* = nichts kopiert (OK)
"Anfrage" *.MSG = alle *.MSG wurde kopiert (Fehler)
"Anf rage" *.MSG = nichts kopiert (OK)
"090001" *.* = nichts kopiert (hier hätte es eine "unechte" *.msg gegeben (Fehler))
"code/artcurr" *.msg = nichts kopiert (hier hätte es eine "unechte" *.msg gegeben (Fehler))
"10310668" *.* = nichts kopiert (hier hätte es zwei *.txt gegeben (Fehler))

Ergebnis Szenario 1: Die Formel scheint nicht zu funktionieren ... oder habe ich einen Fehler?


Szenario 2:
$searchstring = '10310668'  
$source = 'C:\xxx'  
$destination = 'C:\xxx'  
gci $source -Filter *.* -recurse | ?{(gc $_.Fullname -Encoding Unicode | out-string) -like "*$searchstring*" } | move-item -Destination $destination -force -verbose  

"Anfrage" *.* = nur die echte und richtige *.msg kopiert (OK)
"Anf rage" *.* = nichts kopiert (OK)
"Anfrage" *.MSG = nur die echte und richtige *.msg kopiert (OK)
"Anf rage" *.MSG = nichts kopiert (OK)
"090001" *.* = nichts kopiert (hier hätte es eine "unechte" *.msg gegeben (Fehler))
"code/artcurr" *.msg = nichts kopiert (hier hätte es eine "unechte" *.msg gegeben (Fehler))
"10310668" *.* = nichts kopiert (hier hätte es zwei *.txt gegeben (Fehler))


Ergebnis Szenario 2: Die Formel scheint für "richtige" Outlook-*.msg zu funktionieren, nur meine "falschen" *.msg werden nicht angesprochen. Kann man die Formel ggf. auch auf andere Dateien (*.txt) umstellen?


Szenario 3:
clear-host

$source = 'C:\xxx'  
$destination = 'C:\xxx'  

$files = gci $source

foreach ($f in $files){
    $match = $false
    $content = gc $source\$f
    foreach ($c in $content){
        switch($c){
            "161107 100047 EAN load //TXU/data/barcode/artcurr.dat 10486 (OK)"{$match = $true}  
        }
    }
    if ($match -eq $true){
        Move-Item $source\$f -Destination $destination
    }
}
"Anfrage" = nichts kopiert (hier hätte es eine richtige *.msg gegeben (Fehler))
"Anf rage" = nichts kopiert (OK)
"090001" = nichts kopiert (hier hätte es eine "unechte" *.msg gegeben (Fehler))
"code/artcurr" = nichts kopiert (hier hätte es eine "unechte" *.msg gegeben (Fehler))
wird nach einem Text-Teil innerhalb der Datei gesucht, also nicht die ganze Zeile so wie sie in der zu durchsuchenden Datei vorkommt, dann wird keine Datei verschoben
wird die gesamte Zeile innerhalb der Datei gesucht, also so wie sie in der zu durchsuchenden Datei vorkommt, dann wird die Datei verschoben
"10310668" = nur eine *.txt (Textdokument2.txt) kopiert, hier hätte es zwei gegeben (Falsch)

Ergebnis Szenario 3: Die Formel scheint für Textdateien (in meinem Fall die beiden *.txt und aber auch die "falschen" *.msg) eingeschränkt zu funktionieren. In der Suche muss immer die gesamte Zeile 1:1 so eingegeben werden, wie sie auch in der zu durchsuchenden Datei vorzufinden ist. Das ist nur bedingt hilfreich, da mein Suchbegriff "irgendwo" im Txxt vorkommen kann ... kann man das ggf. noch anpassen?

Ich hoffe man kann meine Beschreibung halbwegs nachvollziehen ... um Hilfe bin ich dankbar.

Gruß
Con
colinardo
colinardo 19.11.2016 aktualisiert um 09:34:49 Uhr
Goto Top
um Hilfe bin ich dankbar.
Drei vier deiner Dateien gezippt zur Verfügung stellen und das simple Thema wäre schon längst erledigt, und die aufwendige Testerei unnötig gewesen! Das ist doch nur trial & error was du da treibst. Für uns ist das ein einfacher Blick in die Raw-Daten der Datei dann können wir dir das passende Skript liefern. Alles andere wäre hier Glaskugel polieren. DANKE!

Du siehst ja in meinem zweiten Script gehe ich davon aus das alle Dateien im Unicode vorliegen (-Encoding Unicode). Ob das der Fall ist kann ich ja von hier aus nicht wissen, denn die Annahme beruhte darauf das es sich um binäre E-Mail Dateien handelt, die meist im Unicode Format vorliegen. Auch das war Spekulation, also bitte helfe uns damit wir dir "effektiv" helfen können. Dazu eine "klare" Beschreibung welche Arten von Dateien vorkommen können, wie gesucht werden soll etc. pp., dann ist das hier mit einem Post abgehandelt!
Vom Encoding hängt es ab wie die Daten von der Shell interpretiert werden und ob Strings korrekt gefunden werden oder eben nicht, dazu müssen wir wissen was für Files du da hast.
Wenn ich klar weis das mixed files vorkommen können kann man eine zusätzliche dafür Abfrage einbauen, da nicht jede Datei ein BOM enthält, aber eben nur wenn man das weiß.
Concurve
Concurve 21.11.2016 um 14:58:45 Uhr
Goto Top
So, ich möchte mich nun noch einmal zu diesem Thema zu Wort melden.

1. Ein Dankeschön an Tiberius und ein dickes Dankeschön an colinardo für die grandiose Hilfe und final auch für die Lösung meines Problems, wirklich großartig!


2. Möchte ich für alle, die vergleichbare Funktionen suchen, hier noch einmal eine finale Zusammenfassung des Themas aufzeigen.

Bestimmte Wörter in gespeicherten E-Mails *.msg-Dateien suchen und diese E-Mails dann in Ordner xy verschieben/kopieren:
$objOL = new-object -Com Outlook.Application
$searchstring = 'Hier den oder die Suchbegriffe eintragen ...'  
$source = 'C:\.......'  
$destination = 'C:\.......'  
gci $source -Filter *.MSG -recurse | %{
    $mail = $objOL.CreateItemFromTemplate($_.Fullname)
    if ($mail.Body -like "*$searchstring*"){  
         $_ | move-item -Destination $destination -Force -Verbose
    }
    $mail.Close(1)
}


Bestimmte Wörter in ANSI-Textdateien suchen (in meinem Fall *.msg und *.txt - die *.msg ist jedoch KEIN Outlook-Element!) und diese Textdateien dann in Ordner xy verschieben/kopieren:
$searchstring = 'Hier den oder die Suchbegriffe eintragen ...'  
$source = 'C:\.......'  
$destination = 'C:\.......'  
gci "$source\*" -Include '*.msg','*.txt' -recurse | ?{(gc $_.Fullname -Encoding Default | out-string) -like "*$searchstring*" } | move-item -Destination $destination -force -verbose  


Vielen Dank

Gruß
Con