rudizone
Goto Top

Script zum ersetzen eines String anhand einer definierten Liste

Hallo,

ich benötige ein Script, das einen Ordner permanent überprüft.

Sollte eine neue Datei dort hinterlegt werden, so soll das Script diese nach einem bestimmten String durchsuchen und diesen überschreiben bsp. "K0010 1" ändern in "K0010 5463"
und anschliessend die Datei in einen anderen Ordner verschieben.

Das erstetzen soll anhand einer Liste erfolgen bsw.:
"K0010 1"="K0010 5463"
"K0010 2"="K0010 5469"
"K0010 2"="K0010 5449"

Ist sowas einfach zu realisieren? Es sollte permanent im Hintergrund laufen.

Danke

Sascha

Content-Key: 611539

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

Printed on: April 25, 2024 at 10:04 o'clock

Member: TK1987
Solution TK1987 Oct 09, 2020 updated at 10:13:36 (UTC)
Goto Top
Moin Sascha,

mit Powershell:
$Source = 'C:\Quellordner'  
$Interval = 60
$Destination = 'C:\Zielordner'  

$replace = @{
  "K0010 1" = "K0010 5463"  
  "K0010 2" = "K0010 5469"  
  "K0010 3" = "K0010 5449"  
  }

$replace = ($replace.keys | %{"-replace '$_','$($replace.$_)'"}) -Join ' '  

while ($true)  {
  $Files = ls $Source -File
  if ($Files) {
    $Files | % {
      try {
        iex "'$(cat -enc utf8 -raw $_.Fullname)' $replace" -ea stop | Out-File -enc utf8 "$Destination\$_" -ea stop  
        rm $_.Fullname -ea stop
        } catch {write-host -f 'red' $_.Exception.Message}  
      }
    }
  sleep $Interval
  }

Der Ordner $Source wird alle $Interval Sekunden auf Dateien überprüft. Sind welche vorhanden, werden diese ersetzt und in den $Destination-Ordner geschrieben. Sofern der Vorgang erfolgreich war, wird die Datei anschließend in $Source gelöscht.

Die Liste $replace (Zeile 5-9) kann beliebig erweitert werden.

Gruß Thomas
Member: rudizone
rudizone Oct 09, 2020 at 10:12:09 (UTC)
Goto Top
Soweit scheint das zu funktionieren, jedoch nur wenn ich die Datei mit dem Skipt in das Quellverzeichniss schiebe.

wenn ich diese z.b. vom Desktop starte so überprüft er irgendwie den ganzen Desktop und kopiert diesen.

Kann man in Powershell auch ausblenden was er gerade macht?

Schonmal danke für die schnelle Hilfe.
Member: TK1987
TK1987 Oct 09, 2020 updated at 10:38:21 (UTC)
Goto Top
Zitat von @rudizone:
Soweit scheint das zu funktionieren, jedoch nur wenn ich die Datei mit dem Skipt in das Quellverzeichniss schiebe.

wenn ich diese z.b. vom Desktop starte so überprüft er irgendwie den ganzen Desktop und kopiert diesen.
Ach sorry, hatte die $Source Variable nachträglich geändert und vergessen, dies auch in dem Befehl zum auflisten der Dateien zu tun. Habe das oben nun korrigiert.

Kann man in Powershell auch ausblenden was er gerade macht?
Ja.

Man kann...
  • das Skript mit der Zusatzoption -WindowStyle Hidden starten lassen (allerdings würde es dann nicht ganz trivial, wenn man das Skript stoppen möchte)
  • das Skript über die Aufgabenplanung starten lassen

In deinem Fall wäre wohl letzteres empfehlenswerter.

Aufgabe erstellen -> unter Registerkarte Allgemein "unabhängig von der Benutzeranmeldung ausführen" anhaken, dadurch wird das Skript im Hintergrund ausgeführt.
Unter Registerkarte Aktion auf neu -> unter Programm/Skript trägst du nur powershell.exe ein - und bei Argumente dann -EP ByPass -File "C:\Pfad\zum\Skript.ps1"
Optional kannst du dann unter Registerkarte Trigger noch einstellen, ob das Skript automatisch gestartet werden soll.
Member: rudizone
rudizone Oct 09, 2020 at 11:05:30 (UTC)
Goto Top
OK Super das funktioniert soweit schonmal.

jetzt gibt es noch ein Problem, hier meine Liste:
"K0010 1" = "K0010 5274"
"K0010 2" = "K0010 5275"
"K0010 3" = "K0010 5276"
"K0010 4" = "K0010 5277"
"K0010 5" = "K0010 5278"
"K0010 6" = "K0010 5279"
"K0010 7" = "K0010 5201"
"K0010 8" = "K0010 5202"
"K0010 9" = "K0010 5203"
"K0010 10" = "K0010 5200"
"K0010 11" = "K0010 5210"
"K0010 12" = "K0010 5220"
"K0010 13" = "K0010 5230"
"K0010 14" = "K0010 5240"
"K0010 15" = "K0010 5250"
"K0010 16" = "K0010 5260"
"K0010 17" = "K0010 5270"
"K0010 18" = "K0010 5271"
"K0010 19" = "K0010 5272"
"K0010 20" = "K0010 5273"
"K0010 61" = "K0010 5280"
"K0010 62" = "K0010 5281"
"K0010 63" = "K0010 5282"
"K0010 64" = "K0010 5283"
"K0010 65" = "K0010 5284"
"K0010 66" = "K0010 5285"
"K0010 67" = "K0010 5286"
"K0010 68" = "K0010 5287"
"K0010 69" = "K0010 5288"
"K0010 70" = "K0010 5289"
"K0010 71" = "K0010 5290"
"K0010 72" = "K0010 5291"
"K0010 73" = "K0010 5292"
"K0010 74" = "K0010 5293"
"K0010 75" = "K0010 5294"

wenn ich jetzt K0010 1 in dem Feld stehen habe, ersetzt er dieses mit dem richtigen Wert.

steht aber K0010 2 drin macht er K0010 5278275 daraus.
Member: TK1987
Solution TK1987 Oct 09, 2020 at 11:18:20 (UTC)
Goto Top
Stimmt, weil er danach "K0010 5..." wieder ersetzt.

Ändere mal Zeile 11 wie folgt ab:
$replace = ($replace.keys | %{"-replace '$_(?!\d)','$($replace.$_)'"}) -Join ' '  
Member: rudizone
rudizone Oct 09, 2020 at 11:37:19 (UTC)
Goto Top
Mega geil ;) klappt.

Jetzt noch zwei Schönheitskorrekturen kann man wenn ich das nicht im Hintergrund laufen lassen möchte, einen festen Text im Powershell Fenster anzeigen lassen?

sowie den Fensternamen anpassen?
Member: TK1987
TK1987 Oct 09, 2020 updated at 13:14:40 (UTC)
Goto Top
sowie den Fensternamen anpassen?
Einfach folgendes an den Anfang des Skripts:
$Host.UI.RawUI.WindowTitle = 'Beliebiger Fenstertitel'  

kann man wenn ich das nicht im Hintergrund laufen lassen möchte, einen festen Text im Powershell Fenster anzeigen lassen?
klar geht das.

Im Fenster Text ausgeben macht man mit dem Befehl write-host.

Was verstehst du unter "fester" Text? Einfach sowas wie "Skript wird ausgeführt" oder wäre es in dem Fall nicht besser, auch ein bisschen Statusupdates mit auszugeben, z.B.:
$Host.UI.RawUI.WindowTitle = 'Beliebiger Fenstertitel'  
$Source = 'C:\Quellordner'  
$Interval = 60
$Destination = 'C:\Zielordner'  

$replace = @{
  "K0010 1" = "K0010 5463"  
  "K0010 2" = "K0010 5469"  
  "K0010 3" = "K0010 5449"  
  }

$replace = ($replace.keys | %{"-replace '$_(?!\d)','$($replace.$_)'"}) -Join ' '  

write-host "$((get-date).ToString("[dd.MM.yyyy HH:mm]")) Skript wird ausgeführt. "  

while ($true)  {
  $Files = ls $Source -File
  if ($Files) {
    $Files | % {
      try {
        write-host -n "$((get-date).ToString("[dd.MM.yyyy HH:mm]")) Datei '$_' wird verabeitet... "  
        iex "'$(cat -enc utf8 -raw $_.Fullname)' $replace" -ea stop | Out-File -enc utf8 "$Destination\$_" -ea stop  
        rm $_.Fullname -ea stop
        write-host -f green "erfolgreich. "  
        } catch {write-host -f 'red' $_.Exception.Message}  
      }
    }
  sleep $Interval
  }
Member: rudizone
rudizone Oct 09, 2020 at 12:50:28 (UTC)
Goto Top
Super, schonmal besten dank für die Kompetente Hilfe.

Bin nicht mehr am PC, aber werde mir den Vorschlag mal angucken.
Es würde mir eigentlich auch einfach ein Text reichen „Skript wird ausgeführt“.

Wenn man recht einfach Status updates machen kann, werde ich mir das bei Gelegenheit mal angucken.
Member: rudizone
rudizone Oct 13, 2020 at 06:42:45 (UTC)
Goto Top
Lösung funktioniert soweit,

Jedoch ist gerade ein kleines Problem aufgetaucht.

Innerhalb der Datei, kommen die Felder teilweise mehrfach vor, jedoch bekommen sie einen fortlaufenden Index bsp.: K1001/1; K1001/2

Es müssten jedoch alle umgeschrieben werden, und er sollte den Index dabei nicht anrühren.

Ist sowas möglich?
Member: TK1987
TK1987 Oct 13, 2020 at 07:16:52 (UTC)
Goto Top
Geht alles... jedoch habe ich noch nicht ganz verstanden, was genau du da tun willst.

Das soll jetzt zusätzlich zu dem anderen ersetzt werden? Ist das nur eine einzelne Nummer (also K1001), oder sind das wieder mehrere?
Member: rudizone
rudizone Oct 13, 2020 at 10:06:58 (UTC)
Goto Top
Kleines Beispiel
K1001 4
K1001/1 4
K1001/2 4

Soll zu
K1001 5234
K1001/1 5234
K1001/2 5234
Member: TK1987
TK1987 Oct 13, 2020 updated at 12:32:53 (UTC)
Goto Top
Achsooo...

dann müssen wir das ein wenig umstricken:
$Host.UI.RawUI.WindowTitle = 'Beliebiger Fenstertitel'  
$Source = 'C:\Quellordner'  
$Interval = 60
$Destination = 'C:\Zielordner'  

$replace = @{
  "K0010 1" = "5463"  
  "K0010 2" = "5469"  
  "K0010 3" = "5449"  
  }
  
$replace = $replace.keys | %{"-replace '$($_ -replace '^(\S+)','($1(/\d+)?)')(?!\d)','`$1 $($replace.$_)'"}  

write-host "$((get-date).ToString("[dd.MM.yyyy HH:mm]")) Skript wird ausgeführt. "  

while ($true)  {
  $Files = ls $Source -File
  if ($Files) {
    $Files | % {
      try {
        write-host -n "$((get-date).ToString("[dd.MM.yyyy HH:mm]")) Datei '$_' wird verabeitet... "  
        iex "(cat -enc utf8 '$($_.Fullname)') $replace"  | Out-File -enc utf8 "$Destination\$_" -ea stop  
        rm $_.Fullname -ea stop
        write-host -f green "erfolgreich. "  
        } catch {write-host -f 'red' $_.Exception.Message}  
      }
    }
  sleep $Interval
  }
Wichtig: In dem $replace-Hashtable (Zeile 6-10) darf jetzt hinter dem Gleichzeichen jeweils nur noch die Nummer stehen, die eingefügt werden soll - also nicht mehr der KXXXX-prefix.