PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Powershellskript zum Kopieren von Dateien


Platos
2023-11-26, 00:30:47
Also ich habe heute ziemlich lange versucht (mit ChatGPT) ein powershell script zu erstellen, dass folgendes tut (aber es wollte einfach nicht klappen):

Kurzfassung:

Ich habe .dds Dateien verstreut in einem Ordner, der sehr viele unterordner hat. Ich versuche also ein Powershellskript zu machen, die mir diese .dds Dateien sucht und dann in einen von mir definierten Ordner kopiert. Dann werde ich diese .dds Dateien (das sind texturen) upscalen und nachher sollen diese upgescalte .dds Dateien (die den gleichen Dateinamen besitzen werden), wieder an den ursprünglichen Speicherort kopiert werden. Also dort, wo die .dds Dateien vor dem "herauskopieren" gelegen haben. Das Zurückkopieren findet aber erst Tage später statt und auch nicht mehr in der selben Powershell. Man muss also später die .dds Dateien wieder dem ursprünglichen Speicherort "zuweisen" können.

Jetzt kommt die Schwierigkeit: Die .dds Dateien müssen anhand des .dds-Formates "sortiert" werden beim rauskopieren. Also es soll für jedes .dds-Format ein eigener Ordner erstellt werden in die dann nur die .dds Files kommen sollen, die auch dieses dds-format haben.

Das wichtige ist nun, dass das .dds Format jeweils in einer .txt Datei steht. Diese .txt Datei hat den selben Dateinamen, wie die .dds Datei und befindet sich auch im selben Unterordner, wie die .dds Datei. In der .txt Datei steht "DDSFormat=" und hinter dem "=" steht dann das DDS Format.

Man kann also sagen, dass es für jede .txt Datei, die den Inhalt "DDSFormat=" hat, eine gleichnamige .dds Datei gibt (im gleichen unterordner). Und in der .txt Datei steht hinter dem "DDSFormat=" das dds-Format.

Ist nun folgendes möglich?:

1. Ich habe einen Ordner (den ich angeben will). Dieser Ordner soll nach .txt dateien durchsucht werden und auf den Inhalt "DDSFormat=" geprüft werden. Wenn die Textdatei das beinhaltet, soll zwischengespeichert werden, was (noch in der gleichen Zeile) hinter dem "=" steht.
- Nun ist es so, dass es für jede .txt Datei eine .dds Datei geben sollte, die den gleichen Namen hat und im gleichen Unterordner sitzt.
2. Es soll nun nach .dds Dateien gesucht werden, die den gleichen Namen haben, wie diejenigen .txt Dateien, in denen man "DDSFomat=" gefunden hat. Es soll gar nicht erst versucht werden, nach .dds Dateien zu jeder .txt datei zu suchen. Also es wäre einfach unnötig.
3. Nun soll der Speicherort dieser .dds Dateien (und eine Zuordnung der jeweiligen .dds Datei zum jeweiligen Pfad) in eine csv-Datei gespeichert werden. Es soll später möglich sein (anhand der csv. Datei), die .dds Datei diesem ursprünglichen Pfad zuzuordnen, auch wenn die .dds file nicht mehr am gleichen Ort ist (mehr dazu gleich). Gespeichert wird die Datei in einem outputFolder, den ich angeben will.
4. Die .dds Dateien sollen nun anhand des Wertes, der hinter "DDSFormat=" ausgelesen wurde (in der gleichnamigen .txt Datei), in einen Ordner kopiert werden und zwar in ein Ordner mit dem Namen des Wertes hinter "DDSFormat="). Dieser Ordner soll im outputfolder erstellt werden. Also wenn beispielsweise hinter "DDSFormat=" der Wert "DXT5" steht, soll diejenige .dds Datei, die den selben Namen hat, wie diese .txt Datei, in den Ordner "DXT5" kopiert werden (und dieser Ordner soll ja im outputFolder sein bzw. dort automatisch erstellt werden).

Nun werde ich selber die .dds Dateien upscalen. Die upgescalte Dateien werden im gleichen Ordner verbleiben und die gleichen Dateinamen haben. Wenn man nur Pfade und Dateinamen betrachtet, ist es also so, als hätte sich nichts geändert. Diese upgescalten .dds Dateien sollen nun wieder an den ursprünglichen Speicherort zurückkopiert werden. Also dort hin, wo es in der csv-Datei steht.

Ich habe folgendes Script (bzw chatGPT) geschrieben: ```powershell
# Funktion zum Durchsuchen der Datei nach "DDSFormat="
function Search-DDSFormat {
param (
[string]$filePath
)
$content = Get-Content -Path $filePath
$match = $content | Select-String -Pattern "DDSFormat=(.*)"
if ($match) {
$match.Matches.Value -replace "DDSFormat="
}
}

# Ordner durchsuchen und .dds Dateien kopieren
$rootFolder = "PFAD\ZUM\ORDNER"
$outputFolder = "PFAD\ZUM\ZIELODRNER"
$csvPath = "PFAD\ZUR\CSV-DATEI\mapping.csv"
$mapping = @()

$files = Get-ChildItem -Path $rootFolder -Recurse -Filter *.txt
foreach ($file in $files) {
$result = Search-DDSFormat -filePath $file.FullName
$ddsFile = Get-ChildItem -Path (Split-Path $file.FullName) -Filter ($file.BaseName + ".dds") -Recurse
if ($ddsFile) {
$mapping += [PSCustomObject]@{
TxtFileName = $file.FullName
DdsFilePath = $ddsFile.FullName
DDSFormat = $result
}
$destinationFolder = Join-Path -Path $outputFolder -ChildPath $result
if (-not (Test-Path $destinationFolder)) {
New-Item -ItemType Directory -Path $destinationFolder
}
Copy-Item -Path $ddsFile.FullName -Destination $destinationFolder
} else {
Write-Host "Keine .dds-Datei gefunden für $($file.FullName)"
}
}

# Schreiben des $mapping-Arrays in die CSV-Datei
$mapping | Export-Csv -Path $csvPath -NoTypeInformation
```

Skript 2 (zum Lesen der CSV-Datei und Zurückkopieren der .dds-Dateien an ihren ursprünglichen Speicherort):
```powershell
# Lesen der CSV-Datei mit den Zuordnungen von .txt- zu .dds-Dateien
$mapping = Import-Csv -Path "PFAD\ZUR\CSV-DATEI\mapping.csv"

foreach ($entry in $mapping) {
$txtFile = $entry.TxtFileName
$ddsFile = $entry.DdsFilePath
Copy-Item -Path $ddsFile -Destination (Split-Path $txtFile)
}
```

Das Problem: Es wird keine csv Datei erstellt und es wird im übrigen auch immer versucht, eine .dds Datei für .txt dateien zu finden, die gar kein "DDSFormat=" beinhalten. Ich glaube, es wird einfach versucht, für jede .txt Datei eine .dds Datei zu finden (das weiss ich deshalb, weil ich in einer späteren Version des scripts eingebaut habe, dass es mir alle treffer von .txt und .dds dateien ausgeben soll bzw. ein unterschied in der anzahl).

Ansonsten geht das skript 1, glaube ich. Alle .dds Files wurden anhand ihres dds-formats in einen Ordner kopiert.

Ich habe das script versucht mit chatGPT zum laufen zu bringen, aber chatGPT macht es nur noch immer schlimmer. Baut irgend eine Funktion ein und löscht dabei "ausversehen" (wie er so oft sagt) einfach andere Teile wieder raus. So funktioniert irgendwann sogar manchmal gar nichts mehr

Solche Dinge wie "Überprüfe das Skript, ob es auch wirklich funktioniert" hilft auch nicht. Er erkennt nie Fehler und wenn man ihn auf Fehler hinweist, versucht er krampfhaft irgendwas zu ändern, hat aber den Überblick nicht und dann werden wieder ständig Dinge raus gelöscht, die vorher mal da waren oder Dinge nicht mehr beachtet.

Ich sterbe hier xD

Kann mir jemand helfen ?

Ich habe auch noch viele andere Skripte, die aber alle zu nichts geführt haben, also habe ich das genommen, um es hier zu posten.

konkretor
2023-11-26, 10:30:43
Schau mal ich habe meinen speziellen GPT der nur für Powershell etc ist.
Den habe ich mal gefüttert.

Probier den mal aus, vielleicht hat der Bot das Problem vom anderen Bot gehoben :D

Ich schick dir dann noch die Unterhaltung mit dem Bot.
Wenns klappt, bitte hier die Lösung rein posten. Würde mich intressieren obs gelöst wurde.







# Funktion zum Durchsuchen der Datei nach "DDSFormat="
function Search-DDSFormat {
param ([string]$filePath)
$content = Get-Content -Path $filePath
$match = $content | Select-String -Pattern "DDSFormat=(.*)"
if ($match) {
return $match.Matches.Groups[1].Value
}
return $null
}

# Ordner durchsuchen und .dds Dateien kopieren
$rootFolder = "PFAD\ZUM\ORDNER"
$outputFolder = "PFAD\ZUM\ZIELODRNER"
$csvPath = "PFAD\ZUR\CSV-DATEI\mapping.csv"
$mapping = @()

# Suche zuerst alle .txt Dateien
$txtFiles = Get-ChildItem -Path $rootFolder -Recurse -Filter *.txt
foreach ($file in $txtFiles) {
$ddsFormat = Search-DDSFormat -filePath $file.FullName
if ($ddsFormat) {
$ddsFile = Get-ChildItem -Path (Split-Path $file.FullName) -Filter ($file.BaseName + ".dds") -Recurse
if ($ddsFile) {
$mapping += [PSCustomObject]@{
TxtFileName = $file.FullName
DdsFilePath = $ddsFile.FullName
DDSFormat = $ddsFormat
}
$destinationFolder = Join-Path -Path $outputFolder -ChildPath $ddsFormat
if (-not (Test-Path $destinationFolder)) {
New-Item -ItemType Directory -Path $destinationFolder
}
Copy-Item -Path $ddsFile.FullName -Destination $destinationFolder
} else {
Write-Host "Keine .dds-Datei gefunden für $($file.FullName)"
}
}
}

# Schreiben des $mapping-Arrays in die CSV-Datei
$mapping | Export-Csv -Path $csvPath -NoTypeInformation









Ein anderer Ansatz wäre über eine SQLite DB zu gehen





CREATE TABLE DDSFiles (
FileName TEXT PRIMARY KEY,
FilePath TEXT,
DDSFormat TEXT,
FileHash TEXT
);










# SQLite-Modul importieren
Import-Module PSSQLite

# Pfad zur SQLite-Datenbank
$dbPath = "Pfad\zu\Ihrer\Datenbank.db"

# Funktion, um den Hash-Wert einer Datei zu berechnen
function Get-FileHashValue {
param ([string]$filePath)
try {
$hash = Get-FileHash -Path $filePath -Algorithm SHA256
return $hash.Hash
} catch {
Write-Host "Fehler beim Berechnen des Hash-Werts für $filePath"
}
}

# Funktion, um das DDS-Format aus einer .txt-Datei zu lesen
function Get-DDSFormat {
param ([string]$txtFilePath)
try {
$content = Get-Content -Path $txtFilePath
$match = $content | Select-String -Pattern "DDSFormat=(.*)"
if ($match) {
return $match.Matches.Groups[1].Value
}
} catch {
Write-Host "Fehler beim Lesen von $txtFilePath"
}
}

# Funktion, um Daten in die SQLite-Datenbank einzufügen
function Insert-DDSFileInfo {
param ($fileName, $filePath, $ddsFormat, $fileHash)
Invoke-SqliteQuery -DataSource $dbPath -Query "INSERT INTO DDSFiles (FileName, FilePath, DDSFormat, FileHash) VALUES ('$fileName', '$filePath', '$ddsFormat', '$fileHash')"
}

# Hauptskript
$rootFolder = "PFAD\ZUM\ORDNER"

# Suche nach .txt-Dateien und entsprechenden .dds-Dateien
$txtFiles = Get-ChildItem -Path $rootFolder -Recurse -Filter *.txt
foreach ($txtFile in $txtFiles) {
$ddsFormat = Get-DDSFormat -txtFilePath $txtFile.FullName
if ($ddsFormat) {
$ddsFilePath = [IO.Path]::ChangeExtension($txtFile.FullName, ".dds")
if (Test-Path $ddsFilePath) {
$fileHash = Get-FileHashValue -filePath $ddsFilePath
Insert-DDSFileInfo -fileName (Split-Path $ddsFilePath -Leaf) -filePath $ddsFilePath -ddsFormat $ddsFormat -fileHash $fileHash
}
}
}

Platos
2023-11-26, 13:48:44
Vielen dank für deine Rückmeldung.

Also es ist so, es solll für jedermann möglichst einfach sein, also deswegen die Powershell, die hald auf jedem (Windows-) PC schon da ist und man müsste dann quasi nur noch copy-paste machen.

Bezüglich des Powershell-scripts: Also vom Verhalten her gesehen tut es das Selbe, wie mein Skript oben. Es wird keine csv Datei erstellt. Ansonsten werden genau die gleichen Ordner mit den gleichen (und gleich vielen) Dateien erstellt. Es wird auch keine Fehlermeldung ausgegeben in der Powershell.

Ich hatte gestern auch erhebliche Probleme mit der Fehlerbehebung bzw. Diagnose. Ich habs einfach nicht hingekriegt, dass ChatGPT mir ne funktionerende diagnose mit einbaut.

Ich habe bisher folgendes (in meinem Skript) versucht:

1. Anzahl vergleichen lassen von: .txt Dateien (mit "DDSFormat="), .dds Dateien, die dann gefunden wurden und .dds Dateien, die dann kopiert wurden. Und die Angabe des Pfades der Dateien, zu denen dann keine .dds gefunden wurde. Allgemein habe ich gester sehr viele Skripts versucht machen zu lassen. Am Ende lief es immer darauf hinaus, dass jedes Powershell-Script alle .txt Dateien gematch hat (fälschlicherweise), aber die .dds Dateien korrekt. Es kommt mir also so vor, als würde die Suche nach gleichnamigen .dds Dateien auf alle .txt dateien angewandt und nicht nur auf die. die "DDSFormat=" beinhalten. Ich habe chatgpt auch mehrmals aufgefordert, dass er das doch bitte so umsetzen soll und dann kam immer sowas im Prinzip "Habs jetzt geändert". Es hat sich aber immer genau gleich verhalten. Eigentlich ist das nicht so wichtig. Im Endeffekt werden korrekt alle .dds kopiert, die kopiert werden sollen. Es ist eigentlich gar nicht relevant, ob für gewisse .txt Files keine .dds gefunden wird. Ich dachte nur, dass das möglicherweise einen Einfluss auf das Problem mit der csv-datei hat.

- Ich habe dann ebenfalls versucht herauszufinden, warum das mit der csv nicht funktioniert und habe dann einbauen lassen, dass ausgegeben werden soll, ob die csv erstellt wurde und dass vor dem schreiben der Daten in die csv zuerst einmal ausgelesen werden soll, ob die daten überhaupt in dieser mapping-variable gespeichert ist. Und das war sie nie. Aber ich habe ihn dann nicht mehr dazu bringen können, das genau zu untersuchen. Es hat sich dann irgendwie ständig im Kreis gedreht und er hat mir immer wieder das gleiche vorgeschlagen, was ich nicht wollte.
Ich wollte ihn eig. dazu bringen, dass ich herausfinde, warum die Daten nicht in die Mapping-variable geschrieben werden. Hat aber nicht geklappt.

Bezüglich dem Chatverlauf: Habe ich mir angesehen. Also bei mir wurden ähnliche Problembehandlungs-Lösungsvorschläge gebracht. Nicht ganz so gut formuliert zwar. Aber das Problem war ja immer bei mir, dass er das dann nicht so wirklich gut umsetzen konnte in Form eines Skripts.

Frage: Wie kommst du zu einem ChatGPT; der nur für Powershell ist? Musstest du den irgendwie "trainieren" oder wieso ist der nur für sowas? Das ist vermutlich die Bezahlversion oder?

Mit ChatGPT arbeiten ist wie mit einem super intelligenten 2 Jährigen. Einerseits weiss er irgendwie alles, aber andererseits versteht er null Kontext und ich meine wirklich Null. Zumindest eben dort, wo ich das mache (gratis auf ner Webseite).

Edit: Ich habe gerade herausgefunden, dass man mit Bing nun mittlerweile ChatGPT4 auch ohne Anmeldung nutzen kann. Das Gespräch ist jeweils auf 10 Antworten von ChatGPT begrenzt (dann muss man ein neues starten) und meine Antworten sind auf 4000 Zeichen begrenzt jeweils. Das geht klar. Ich nutze jetzt mal den.

Platos
2023-11-26, 14:19:04
Der Übersichtshalber eine neue Antwort:

Habe ChatGPT4 von Bing dazu befragt, er soll mir doch ein paar Debgging-Funktionen einbauen. Habe dann folgenden Code ausführen lassen:

# Funktion zum Durchsuchen der Datei nach "DDSFormat="
function Search-DDSFormat {
param (
[string]$filePath
)
$content = Get-Content -Path $filePath
$match = $content | Select-String -Pattern "DDSFormat=(.*)"
if ($match) {
$match.Matches.Value -replace "DDSFormat="
}
}

# Ordner durchsuchen und .dds Dateien kopieren
$rootFolder = "C:\Users\Gaming-Tower\Pictures\Textur-Upscaling\DDDA\testdds-skript1\enemy"
$outputFolder = "C:\Users\Gaming-Tower\Pictures\Textur-Upscaling\DDDA\testdds-skript1"
$csvPath = "C:\Users\Gaming-Tower\Pictures\Textur-Upscaling\DDDA\testdds-skript1\test-mapping.csv"
$mapping = @()

$files = Get-ChildItem -Path $rootFolder -Recurse -Filter *.txt
if ($files.Count -eq 0) {
Write-Host "Keine .txt-Dateien gefunden im Ordner $rootFolder"
}
foreach ($file in $files) {
$result = Search-DDSFormat -filePath $file.FullName
if (-not $result) {
Write-Host "Keine Übereinstimmung mit 'DDSFormat=' in $($file.FullName)"
}
$ddsFile = Get-ChildItem -Path (Split-Path $file.FullName) -Filter ($file.BaseName + ".dds") -Recurse
if ($ddsFile) {
$mapping += [PSCustomObject]@{
TxtFileName = $file.FullName
DdsFilePath = $ddsFile.FullName
DDSFormat = $result
}
$destinationFolder = Join-Path -Path $outputFolder -ChildPath $result
if (-not (Test-Path $destinationFolder)) {
New-Item -ItemType Directory -Path $destinationFolder
}
Copy-Item -Path $ddsFile.FullName -Destination $destinationFolder
} else {
Write-Host "Keine .dds-Datei gefunden für $($file.FullName)"
}
}

# Überprüfen, ob das $mapping-Array Elemente enthält
if ($mapping.Count -gt 0) {
# Schreiben des $mapping-Arrays in die CSV-Datei
$mapping | Export-Csv -Path $csvPath -NoTypeInformation
} else {
Write-Host "Keine Einträge zum Schreiben in die CSV-Datei gefunden"
}

Das lustige: Jetzt wird eine csv erstellt. Es wird zwar immer noch versucht, für alle .txt eine .dds zu finden, ist aber nicht so schlimm.

Ich habe dann gefragt, warum das jetzt geht, da er ja am skript selbst nichts geändert hat. Seine antwort darauf war: "Es freut mich zu hören, dass das Skript jetzt funktioniert! Die Änderungen, die ich vorgenommen habe, waren in der Tat hauptsächlich für das Debugging gedacht und sollten das Verhalten des Skripts nicht direkt beeinflussen. Allerdings gibt es ein paar Möglichkeiten, wie diese Änderungen indirekt dazu beigetragen haben könnten, dass das Skript funktioniert:

PowerShell-Caching: PowerShell kann manchmal Ergebnisse von vorherigen Befehlen zwischenspeichern. Durch das Hinzufügen der Debugging-Ausgaben könnte PowerShell gezwungen worden sein, die Befehle erneut auszuführen, anstatt zwischengespeicherte Ergebnisse zu verwenden.

Dateizugriffszeit: Das Hinzufügen der Debugging-Ausgaben könnte das Skript verlangsamt haben, was mehr Zeit für den Dateizugriff ermöglicht hätte. Wenn das ursprüngliche Skript zu schnell ausgeführt wurde, könnte es sein, dass einige Dateioperationen nicht abgeschlossen wurden, bevor das Skript versuchte, auf die Dateien zuzugreifen.

Fehlerbehebung: Die zusätzlichen Debugging-Ausgaben könnten Ihnen geholfen haben, ein Problem zu identifizieren und zu beheben, das das ursprüngliche Skript daran gehindert hat, korrekt zu funktionieren.

Es ist wichtig zu beachten, dass diese Möglichkeiten spekulativ sind. Ohne weitere Informationen über die genaue Ausführungsumgebung und die Zustände vor und nach der Ausführung des Skripts ist es schwierig, eine definitive Erklärung zu geben. Ich hoffe, das hilft!"

Ich versuche jetzt das mal mit ihm zu lösen. Ich berichte dann. Der ChatGPT4 in Bign ist auf jeden Fall etwas weniger frustrierend dämlich (bisher).

EDIT: ich habe jetzt mal folgendes gemacht: Ich habe geprüft, ob die $mapping variable daten enthält (und zwar direkt vor dem beschreiben der .csv). --> Das tut sie nicht (wie gesagt).

Ich habe nun aber auch noch geprüft, ob die $mapping variable direkt nach dem beschreiben der variable daten enthält. --> Ja das tut sie. D.h die $mapping variable "verliert" irgendwie den inhalt im verlauf des skriptes. Ich versuche jetzt mal weiter daran zu arbeiten.

Platos
2023-11-26, 16:36:26
(EDIT: Nein, es funktioniert nun auf magische art und weise doch nicht mehr. Wieso auch immer. Was für ein krampf das skript :D)

Aktualisierung:

Ich denke, ich habe das problem jetzt gefunden (für das Skript 1. Skript 2 muss ich noch testen). Das Problem lag glaube ich daran, dass laut ChatGPT die Powershell standartmässig versucht, eine csv Datei in UTF16 zu speichern. Ich bzw. er hat das jetzt so gemacht, dass sie in UTF8 gespeichert wird und so funktioniert es.

Hier ist der Code (der momentan noch viel unnötioges debuggin enthält):

# Funktion zum Durchsuchen der Datei nach "DDSFormat="
function Search-DDSFormat {
param (
[string]$filePath
)
$content = Get-Content -Path $filePath
$match = $content | Select-String -Pattern "DDSFormat=(.*)"
if ($match) {
$match.Matches.Value -replace "DDSFormat="
}
}

# Ordner durchsuchen und .dds Dateien kopieren
$rootFolder = "PFAD\ZUM\ORDNER"
$outputFolder = "PFAD\ZUM\ZIELODRNER"
$csvPath = "PFAD\ZUR\CSV-DATEI\mapping.csv"
$mapping = @()
$ddsFormatFiles = @()

$files = Get-ChildItem -Path $rootFolder -Recurse -Filter *.txt
foreach ($file in $files) {
$result = Search-DDSFormat -filePath $file.FullName
if ($result) {
$ddsFormatFiles += @{
'file' = $file
'format' = $result
}
}
}

foreach ($item in $ddsFormatFiles) {
$file = $item['file']
$result = $item['format']
$ddsFile = Get-ChildItem -Path (Split-Path $file.FullName) -Filter ($file.BaseName + ".dds") -Recurse
if ($ddsFile) {
$mapping += [PSCustomObject]@{
TxtFileName = $file.FullName
DdsFilePath = $ddsFile.FullName
DDSFormat = $result
}
# Überprüfen Sie die Anzahl der Elemente in der $mapping-Variable direkt nach ihrer Beschreibung
Write-Host "`$mapping has $(($mapping | Measure-Object).Count) items after adding a new item"

$destinationFolder = Join-Path -Path $outputFolder -ChildPath $result
if (-not (Test-Path $destinationFolder)) {
New-Item -ItemType Directory -Path $destinationFolder
}
Copy-Item -Path $ddsFile.FullName -Destination $destinationFolder
} else {
Write-Host "Keine .dds-Datei gefunden für $($file.FullName)"
}
}

# Überprüfen Sie die Anzahl der Elemente in der $mapping-Variable direkt vor dem Export in die CSV-Datei
Write-Host "`$mapping has $(($mapping | Measure-Object).Count) items before Export-Csv"

# Schreiben des $mapping-Arrays in die CSV-Datei
$mapping | Export-Csv -Path $csvPath -NoTypeInformation -Encoding UTF8


Ich werde dann berichten, wie es mit dem 2. skript aussieht. Wenn (oder besser falls) es dann klappt, werde ich versuchen, 2 finale skripte dann hier zu posten.

Btw: Wenn man beim edge browser ohne Anmeldung ChatGPT4 nutzt, wird einem standartmässig 10 Antworten (durch ChatpGT) gutegschrieben (pro Anfrage). Wenn man aber schon mit ihm geschrieben hat und dann auf neue Anfrage klickt, wird diese anscheinend (zumindest bei mir bisher) auf 30 erhöht.

Es ist mir aber auch einmal passiert, dass er einfach abgeblockt hat nach 4 Antworten und gesagt hat, er könne mir keine Antwort mehr geben. Dann wurde das ganze geblockt und ich konnte nicht mehr antworten und ich solle doch von vorne anfangen :D

konkretor
2023-11-26, 19:33:34
Ganz spannend das hier wieder UTF in die Suppe spuckt, mein GPT Bot ist ChatGPT4.

Ja manchmal ist es praktisch sich das Skript erst in der Bash basteln zu lassen und dann noch powershell umschreiben zu lassen.

Platos
2023-11-27, 23:44:50
Sooo, ich bin jetzt fertig mit dem Powershell-Skript (bzw. 2 skripts).

Ich habe es nun schon oft benutzt und bisher hat es immer funktioniert.

Das Skript ist ja zugeschnitten auf das Spiel DragonsDogma bzw. es benötigt das ARCtool, welches erstmal alle daten entpackt (und somit überhaupt zugänglich macht) und zu jeder .tex datei eine .txt datei erstellt (mit infos). Anhand dieser Infos kopiere ich dann jede .dds datei in Ordner, die nach dem dds-format benannt sind (die diese .dds dateien haben).

Es ist jetzt so, dass in Spielen Texturen öfters doppelt vorkommen. Mir war das zwar klar, aber ich habe nicht (daran) gedacht, dass die auch alle gleich benannt sind. Das hat dann noch Probleme verursacht. Jetzt werden Duplikate in separate Ordner kopiert, bennant nach dem dds-format & dem Anhängsel "_2" wobei die Zahl 2 hier natürlich auch zu 3, 4 usw. werden kann.

Zusätzlich zum kopiervorgang wird eine .csv datei erstellt, mit der es möglich wird, sich für jede .dds datei den "ursprünglichen" Speicherort zu "merken" (um die Datei später wieder zurück zu kopieren).

Im Skript 2 wird dann genau das gemacht. Die Dateien werden wieder zurückkopiert. Natürlich darf man sie weder umbenennen noch verschieben. Dadurch, dass das Zeug in eine Datei geschrieben wird, kann ich mir so viel Zeit lassen, wie ich will, um die .dds Dateien (texturen) upzusclalen.

Da ich so viele Probleme mit beiden Skripts hatte, habe ich auch unzählige Debugging-funktionen in den Skripts, da ich herausfinden musste, woher die ganzen Probleme kamen. Vorerst lasse ich die aber alle drinn, man weiss ja nie... Vor allem das 2. Skript hat viel Debugging. Besteht quasi zu 90% daraus :biggrin:

Probleme gabs unzählige, aber hier mal die 2 Finalen Skripte (ich packe sie in Spoiler):

Skript1:
# Funktion zum Durchsuchen der Datei nach "DDSFormat="
function Search-DDSFormat {
param (
[string]$filePath
)
$content = Get-Content -Path $filePath
$match = $content | Select-String -Pattern "DDSFormat=(.*)"
if ($match) {
$match.Matches.Value -replace "DDSFormat="
}
}

# Ordner durchsuchen und .dds Dateien kopieren
$rootFolder = "PFAD\ZUM\ORDNER"
$outputFolder = "PFAD\ZUM\ZIELODRNER"
$csvPath = "PFAD\ZUR\CSV-DATEI\mapping.csv"
$mapping = @()
$ddsFormatFiles = @()

$files = Get-ChildItem -Path $rootFolder -Recurse -Filter *.txt
$totalDdsFiles = 0
$totalTxtFiles = 0
$totalCopiedFiles = 0
$totalDuplicates = 0

foreach ($file in $files) {
$result = Search-DDSFormat -filePath $file.FullName
if ($result) {
$totalTxtFiles++
$ddsFormatFiles += @{
'file' = $file
'format' = $result
}
}
}

foreach ($item in $ddsFormatFiles) {
$file = $item['file']
$result = $item['format']
$ddsFile = Get-ChildItem -Path (Split-Path $file.FullName) -Filter ($file.BaseName + ".dds") -Recurse
if ($ddsFile) {
$totalDdsFiles++
$destinationFolder = Join-Path -Path $outputFolder -ChildPath $result
$i = 2
while (Test-Path (Join-Path -Path $destinationFolder -ChildPath $ddsFile.Name)) {
$destinationFolder = Join-Path -Path $outputFolder -ChildPath ($result + "_$i")
$i++
$totalDuplicates++
}
if (-not (Test-Path $destinationFolder)) {
New-Item -ItemType Directory -Path $destinationFolder
}
Copy-Item -Path $ddsFile.FullName -Destination $destinationFolder

# Erstellen Sie den Pfad zur kopierten .dds-Datei
$newDdsFilePath = Join-Path -Path $destinationFolder -ChildPath $ddsFile.Name

$mapping += [PSCustomObject]@{
OldDdsFilePath = $ddsFile.FullName
NewDdsFilePath = $newDdsFilePath
DDSFormat = $result
}
$totalCopiedFiles++
# Überprüfen Sie die Anzahl der Elemente in der $mapping-Variable direkt nach ihrer Beschreibung
Write-Host "`$mapping has $(($mapping | Measure-Object).Count) items after adding a new item"

} else {
Write-Host "Keine .dds-Datei gefunden für $($file.FullName)"
}
}

# Überprüfen Sie die Anzahl der Elemente in der $mapping-Variable direkt vor dem Export in die CSV-Datei
Write-Host "`$mapping has $(($mapping | Measure-Object).Count) items before Export-Csv"

# Ausgabe des `$csvPath`
Write-Host "`$csvPath is: $csvPath"

# Versuch, die $mapping-Variable in eine Datei mit der Add-Content-Funktion anstelle von Export-Csv zu schreiben
try {
$mapping | ConvertTo-Csv -NoTypeInformation -Delimiter "," | Out-String | Set-Content -Path $csvPath -ErrorAction Stop
} catch {
Write-Host "Fehler beim Schreiben der CSV-Datei: $($_.Exception.Message)"
}

# Ausgabe des Ergebnisses des `Set-Content`-Befehls
$result = $mapping | ConvertTo-Csv -NoTypeInformation -Delimiter "," | Out-String | Set-Content -Path $csvPath
Write-Host "`$result is: $result"

# Ausgabe der Gesamtanzahl der gefundenen .dds-Dateien, der kopierten .dds-Dateien und der .txt-Dateien mit "DDSFormat="
Write-Host "Es wurden insgesamt $totalDdsFiles .dds-Dateien gefunden."
Write-Host "Es wurden insgesamt $totalCopiedFiles .dds-Dateien kopiert."
Write-Host "Es wurden insgesamt $totalTxtFiles .txt-Dateien mit 'DDSFormat=' gefunden."

# Ausgabe der Anzahl der Duplikate
Write-Host "Es wurden insgesamt $totalDuplicates Duplikate gefunden."

# Nachdem alle Kopiervorgänge abgeschlossen sind
$specialFolders = Get-ChildItem -Path $outputFolder -Directory | Where-Object { $_.Name -match "_\d+$" }
$totalCopiedDuplicates = 0

foreach ($folder in $specialFolders) {
$totalCopiedDuplicates += (Get-ChildItem -Path $folder.FullName -File | Measure-Object).Count
}

Write-Host "Es wurden insgesamt $totalCopiedDuplicates Duplikate in 'Sonderordner' kopiert."


Skript2:

# Lesen der CSV-Datei mit den Zuordnungen von .txt- zu .dds-Dateien
$mapping = Import-Csv -Delimiter "," -Path "PFAD\ZUR\CSV-DATEI\mapping.csv"

# Erstellen Sie Hashtables, um die Anzahl der Vorkommen jeder Datei zu zählen
$oldFileCounts = @{}
$newFileCounts = @{}

foreach ($entry in $mapping) {
if ($oldFileCounts.ContainsKey($entry.OldDdsFilePath)) {
$oldFileCounts[$entry.OldDdsFilePath]++
} else {
$oldFileCounts[$entry.OldDdsFilePath] = 1
}

if ($newFileCounts.ContainsKey($entry.NewDdsFilePath)) {
$newFileCounts[$entry.NewDdsFilePath]++
} else {
$newFileCounts[$entry.NewDdsFilePath] = 1
}
}

# Überprüfen Sie auf Duplikate in der alten Dateiliste
Write-Host "Duplikate in OldDdsFilePath:"
foreach ($file in $oldFileCounts.Keys) {
if ($oldFileCounts[$file] -gt 1) {
Write-Host "$file erscheint $($oldFileCounts[$file]) Mal."
}
}

# Überprüfen Sie auf Duplikate in der neuen Dateiliste
Write-Host "Duplikate in NewDdsFilePath:"
foreach ($file in $newFileCounts.Keys) {
if ($newFileCounts[$file] -gt 1) {
Write-Host "$file erscheint $($newFileCounts[$file]) Mal."
}
}

# Initialisieren Sie die Zählvariable und die Liste der kopierten Dateien
$successfulCopies = 0
$copiedFiles = @()

foreach ($entry in $mapping) {
$oldDdsFile = $entry.OldDdsFilePath
$newDdsFile = $entry.NewDdsFilePath

# Überprüfen Sie die Pfade in der CSV-Datei
if (!(Test-Path $newDdsFile)) {
continue
}

# Prüfen Sie die Größe der alten Datei
$oldSize = (Get-Item $oldDdsFile).Length

# Kopieren Sie die Datei und fangen Sie Fehler mit Try/Catch
try {
Copy-Item -Path $newDdsFile -Destination $oldDdsFile -ErrorAction Stop
} catch {
Write-Host "Fehler beim Kopieren der Datei: $newDdsFile"
continue
}

# Prüfen Sie die Größe der alten Datei erneut
$newSize = (Get-Item $oldDdsFile).Length

# Überprüfen Sie, ob die Datei erfolgreich kopiert wurde
if ($newSize -gt $oldSize) {
$successfulCopies++
$copiedFiles += $newDdsFile
Write-Host "Die Datei $newDdsFile wurde erfolgreich nach $oldDdsFile kopiert."
}
}

# Geben Sie die Anzahl der erfolgreich kopierten Dateien aus
Write-Host "Es wurden $successfulCopies Dateien erfolgreich kopiert."

# Erstellen Sie ein Hashtable, um die Anzahl der Vorkommen jeder Datei zu zählen
$fileCounts = @{}
foreach ($file in $copiedFiles) {
if ($fileCounts.ContainsKey($file)) {
$fileCounts[$file]++
} else {
$fileCounts[$file] = 1
}
}

# Geben Sie die Dateien aus, die mehr als einmal kopiert wurden
Write-Host "Die folgenden Dateien wurden mehr als einmal kopiert:"
foreach ($file in $fileCounts.Keys) {
if ($fileCounts[$file] -gt 1) {
Write-Host "$file wurde $($fileCounts[$file]) Mal kopiert."
}
}


Edit: Ich überlege mir noch, für alle Powershell-Ausgaben eine .log Datei zu erstellen. Habe ich im Verlauf der Problembehebung auch schon gemacht. Habe es jetzt aber raus genommen. Aber ist nicht zwingend nötig eig.

ChatGPT4 ist wirklich besser, wie das, was ich vorher benutzt hatte (ChatGPT3.5). Aber es ist nur besser, nicht von seinen Fehlern geheilt. Die sind genau die gleichen, nur vlt. minimal weniger. Das reicht aber, um maximal weniger frustriert zu werden :D
Aber so wirklich brauchbar ist auch der nicht. Sonst hätte ich nicht 2 Tage dafür gebraucht...

Platos
2023-11-30, 15:13:20
Wichtig anzumerken wäre noch, dass man auf keinen Fall ein $ Zeichen irgendwo im Pfad haben darf. Das Wird glaube ich von der Powershell als variabel-trigger verstanden.

Und ich würde mal raten, auch sonst auf spezielle Zeichen zu verzichten.

pollux
2023-12-01, 12:18:50
Wichtig anzumerken wäre noch, dass man auf keinen Fall ein $ Zeichen irgendwo im Pfad haben darf. Das Wird glaube ich von der Powershell als variabel-trigger verstanden.

Und ich würde mal raten, auch sonst auf spezielle Zeichen zu verzichten.

Du kannst einen String in einfache Hochkommata setzen, dann werden z.B. Variablen nicht aufgelöst ('anstelle von "). Oder du maskierst einzelne Sonderzeichen mit einem vorangestellten Backtick (`).