Wie kann man Dateien zählen (und) formatieren?

Stelle Fragen zur Programmierung mit Autohotkey

Moderator: jNizM

argy
Posts: 4
Joined: 19 Feb 2022, 13:39

Wie kann man Dateien zählen (und) formatieren?

19 Feb 2022, 13:53

Hallo. Ich bastle gerade an einen Projekt, bei dem Dateien auf eine SD-Karte geschrieben werden.
Es gibt dort (wenn alles korrekt ist) einen Order "mp3" und einen Ordner "advert".
In zusätzliche Ordner die nach dem Muster 001, 002, 003... aufgebaut sind werden dann Dateien rein kopiert.
Das funktioniert soweit auch schon...

Nun möchte ich die Funktionen aber gern erweitern in dem ich eine Möglichkeit einbauen möchte die Ordner mit Zahlen am Anfang (also 001, 002, 003,...) zu löschen.
Die Ordner "mp3" und "advert" sollen nicht gelöscht werden.
Ich habe zwar die Funktion "FileRemoveDir" gefunden, aber der muss ich ja einen Verzeichnisnamen mitgeben.
Oder könnte man das auch per Regex machen? Denn den Pfad der SD-Karte lese ich vorher ein, daher weiß ich welche Dateien da drin sind.
Der Löschvorang soll durch einen Button ausgelöst werden und eine Sicherheitsabfrage beinhalten, ob man die Dateien wirklich löschen möchte.
Ich bin mir nicht sicher ob und wenn ja wie das geht, denn der Vorgang soll auch abgebrochen werden können, wenn man sich verklickt hat.

Des weiteren möchte ich gern eine Art Zählfunktion einbauen die prüft ob und wenn ja wie viele Ordner/Dateien überhaupt auf der Karte sind.
Denn dann kann man eine Funktion bauen die sagt "wenn - größer 0 - zeige "Button zum löschen" - sonst - zeige "Die SD-Karte ist leer".
Dazu habe ich leider nicht wirklich was gefunden, was mir weiterhilft. Eventuell hat jemand ja sowas schon mal gebaut oder eine Idee dazu?

Ich freue mich über Antworten oder Hilfestellungen um bei meinem Vorhaben weiter zu kommen...
Liebe Grüße, Argy
BoBo
Posts: 6564
Joined: 13 May 2014, 17:15

Re: Wie kann man Dateien zählen (und) formatieren?

19 Feb 2022, 18:37

Hallo Argy,
das ist alles machbar.
"Das funktioniert soweit auch schon..."
Wäre gut diesen Code mal zu sehen, um zu wissen wo anzusetzen ist.

Ein Satz an AHK-Befehlen, welche zum Einsatz kommen könnten (einfach anklicken)

Code: Select all

Loop, Files ; (parsen der verzeichnishierarchie)
FileMove ; (verschieben von dateien)
FileAppend ; (schreiben von logs)
Format() ; (zahlenformat buxeln)
Gui ; (benutzeroberfläche)
argy
Posts: 4
Joined: 19 Feb 2022, 13:39

Re: Wie kann man Dateien zählen (und) formatieren?

22 Feb 2022, 13:41

Hallo @BoBo
Hatte leider nicht eher gesehen, das du geantwortet hast...

Der Aktuelle Code schaut wie folgt aus:

Code: Select all

;-------------------------------------------------------------------------------
; TonUINO SDcard Manager
; Manage your SD card for your TonUINO
;-------------------------------------------------------------------------------
; AutoHotkey Version: 1.1.x
; Author:		Benedikt Schneyer 
; Modifier:		Rico Giesler

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
#SingleInstance force ; Only one instance at a time
#NoTrayIcon

SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

;; ***************
;; global settings
;; ***************

VERSION := "0.12.0"
AUDIOPROMPT := "Wähle einen Ordner aus"
SDPROMPT := "Wähle eine SD-Karte aus"
COPYLOG := "copylog.txt"

;; ***********
;; init config
;; ***********

iniPath := "settings.ini"

IniRead, SDPath, % iniPath, % "User", % "SDpath", % SDPROMPT
IniRead, AudioPath, % iniPath, % "User", % "Audiopath", % AUDIOPROMPT
IniRead, AsAdmin, % iniPath, % "User", % "AsAdmin", 0
IniRead, WithFilename, % iniPath, % "User", % "WithFilename", 1
IniRead, SmartRename, % iniPath, % "User", % "SmartRename", 1
IniRead, Recursive, % iniPath, % "User", % "Recursive", 0

;; ************
;; run as admin
;; ************

if (AsAdmin && not A_IsAdmin)
{
	Run *RunAs "%A_ScriptFullPath%"
	ExitApp
}

; MsgBox, % id3read("F:\temp\Tonuino\Auf der Baustelle\01 1.mp3","Artist")

;; ***
;; GUI
;; ***

Gui, New, , TonUINO SD Card manager
Gui, Add, Edit, w300 vSDPathEdit disabled, % SDPath
Gui, Add, Button, gselectSDcard X+m, SD-Karte wählen
Gui, Add, Progress, w200 x10 h20 cGreen vSDSpaceProgress BackgroundAAAAAA, 
Gui, Add, Text, x+m yp+5 vSDSpace w300, NA

Gui, Add, Tab3, w550 x10 y+10, SD-Karte prüfen|Dateien Kopieren|Einstellungen

Gui, Add, Text, vCheck X+10 w530, SD-Karte ist ok
Gui, Add, Edit, vErrors r10 w530
Gui, Add, Button, gRecheck, Test wiederholen

Gui, Tab, Dateien
Gui, Add, Edit, w420 vAudioPathEdit section x+5 y+5 disabled -Multi R1, % AudioPath
Gui, Add, Button, gselectAudio X+m, Ordner auswählen

Gui, Add, Text, vNextFolder Xs+5, Kopieren nach:
Gui, Add, DropDownList, X+m Yp-3 vTargetFolder AltSubmit, Neu||01|02
Gui, Font, bold
Gui, Add, Text,X20 Y+m h30 , Um Dateien in einen vorhandenen Ordner zu kopieren bitte eine Ordnernummer auswählen

Gui, Font,
Gui, Add, Text,X20 Y+m, (Doppelklick auf eine Zeile schaltet zwischen Kopieren und Überspringen um)

Gui, Add, ListView, xs r10 w530 gLVClick AltSubmit, Modus|Dateiname|Titel|Liednummer|Pfad
LV_ModifyCol(3, "Integer")
LV_ModifyCol(4,0)

Gui, Add, Checkbox, vWithFilename checked%WithFilrename% gSaveIni Xs+5 h25, Originalname an Nummer anhängen 
Gui, Add, Checkbox, vSmartRename checked%SmartRename% gSaveIni X+m h25, Smartes umbenennen (Umlaute)
Gui, Add, Checkbox, vRecursive checked%Recursive% gSaveIni X+m h25, Unterordner einbeziehen
Gui, Add, Button, vCopyAudioBut gcopyAudio X20 Y+m, Kopiervorgang starten

Gui, Tab, Einstellungen
Gui, Add, Checkbox, vAsAdmin gSaveIni checked%AsAdmin%, Als Administrator starten (Neustart erforderlich)
Gui, Add, Button, gRestart, TinoTool neu starten

Gui, Tab,
Gui, Add, Link, , <a href="https://github.com/DarthBrento/TinoTool">Projekt auf GitHub</a>
Gui, Add, Text, x+380 , % "Version: " VERSION

Gui, Add, StatusBar,, Fertig

Gui, Show, center autosize, TinoTool

checkSDCard(SDPath)
readFileList(AudioPath)

targetFolder := 1
return

/*
    ######## ##     ## ########  ######     		######## ##    ## ########
    ##        ##   ##  ##       ##    ##    		##       ###   ## ##     ##
    ##         ## ##   ##       ##          		##       ####  ## ##     ##
    ######      ###    ######   ##          		######   ## ## ## ##     ##
    ##         ## ##   ##       ##          		##       ##  #### ##     ##
    ##        ##   ##  ##       ##    ##    		##       ##   ### ##     ##
    ######## ##     ## ########  ######     		######## ##    ## ########
*/

selectSDcard:
	FileSelectFolder, SDPath , ::{20d04fe0-3aea-1069-a2d8-08002b30309d},2, Wähle eine SD-Karte aus
	if (SDPath = "")
		SDPath := SDPROMPT
	GuiControl, , SDPathEdit, % SDPath 

	IniWrite, % SDpath, % iniPath, % "User", % "SDpath"
	checkSDCard(SDPath)
return

selectAudio:
	
	starting := "::{20d04fe0-3aea-1069-a2d8-08002b30309d}"
	
	if (AudioPath != AUDIOPROMPT)
		starting := "*" . AudioPath

	FileSelectFolder, AudioPath , % starting ,2, Wähle einen Ordner aus
	if (AudioPath = "")
		AudioPath := AUDIOPROMPT
	GuiControl, , AudioPathEdit, % AudioPath 

	nextFolder := nextFolder(SDPath)
	
	readFileList(AudioPath)

	IniWrite, % AudioPath, % iniPath, % "User", % "AudioPath"
return


copyAudio:
	Gui, Submit, NoHide
	GuiControl, +Disabled, CopyAudioBut
	SB_SetText("Kopiere Dateien")

	nextFolder := nextFolder(SDPath)

	targetFolderName := targetFoldertoPath(SDPath, targetFolder)
	; MsgBox, % SDPath . "\" . targetFoldertoPath(SDPath, targetFolder)

	FileCreateDir, % SDPath . "\" . targetFolderName
	FileList := ""

	filesC := LV_GetCount()

	; Loop, Files, % AudioPath . "\*.mp3", F 
	; {
	; 	FileList .= A_LoopFileName . "`n"
	; }
	; Sort, FileList

	srcFilename := ""
	nid := 1
	Loop, Files, % SDPath . "\" . targetFolderName . "\*"
		nid++

	srcFolder := ""

	Loop, % LV_GetCount()
	{
		if (nid > 255) 
		{
			MsgBox, % "Fehler: Maximal 255 Dateien pro Ordner möglich"
			Return
		}
		SB_SetText("Kopiere - " . A_Index . "/" . filesC . " nach " . targetFolderName)
		LV_GetText(mode,A_Index)
		LV_GetText(srcFilename,A_Index,2)
		LV_GetText(srcPath,A_Index,5)
		

		folderFile := SubStr(srcPath, InStr(srcPath, "\", false, 0, 2)+1)
		folder := SubStr(folderFile,1, InStr(folderFile, "\") - 1)

		if (srcFolder != folder)
		{
			srcFolder := folder
			FileAppend, % targetFolderName . " -> " . folder , % COPYLOG
		}


		if (mode = "überspringen")
			continue
		filename := Format("{1:03}",nid++)
		if (WithFilename) {
			repFN := RegExReplace(srcFilename,".mp3","")
			if (SmartRename) {
				repFN := smartRename(repFN)
			} 
			filename .= "-" . repFN
		}
		filename .= ".mp3"

		FileCopy, % srcPath, % SDPath . "\" .  targetFolderName . "\" . filename
	}

	checkSDCard(SDPath)
	GuiControl, -Disabled, CopyAudioBut
	SB_SetText("Fertig")
return

LVClick:
	If (A_GuiEvent = "A")
	{
		LV_GetText(mode, A_EventInfo,1)
		If (mode = "kopieren")
			LV_Modify(A_EventInfo, , "überspringen")
		else
			LV_Modify(A_EventInfo, , "kopieren")
	}
return

targetFoldertoPath(SDPath,targetFolder)
{
	; get position of selected element
	targetFolder := targetFolder - 1
	; if its zero use the new 
	if (targetFolder = 0)
		return nextFolder(SDPath)
	Else
		return Format("{1:02}",targetFolder)
}

smartRename(str)
{
	str := StrReplace(str, "�","ae")
	str := StrReplace(str, "�","oe")
	str := StrReplace(str, "�","ue")
	str := StrReplace(str, "�","ss")
	; remove leading digits
	str := RegExReplace(str, "^\d+","")
	; remove non word characters and convert to camelCase
	str := RegExReplace(str, "i)(\W+)(\w)","$U2")

	return str
}

nextFolder(SDPath)
{
	return Format("{1:02}",nFNumb(SDPath))
}

nFNumb(SDPath)
{
	Loop, 99
		If not FileExist(SDPath . "\" . Format("{1:02}",A_Index))
			return A_Index
}

TargetFolderDropDown(SDPath,preselected)
{
	if (preselected = "")
		preselected := 1

	max := nFNumb(SDPath)
	str := "|" . Format("{1:02}",max) . " (Neu)|"
	if (preselected = 1)
		str .= "|"
	Loop, % max - 1
	{
		str .= Format("{1:02}",A_Index) . "|"
		if (A_Index = preselected - 1)
			str .= "|"
	}
	return str	
}

checkSDCard(SDPath)
{
	Global targetFolder

	errors := ""
	; check mp3 folder
	If not FileExist(SDPath . "\mp3") {
		errors .= "Fehlender Ordner: mp3`n"
	}

	; check advert folder
	If not FileExist(SDPath . "\advert") {
		errors .= "Fehlender Ordner: advert`n"
	}

	; check additional folders
	Loop, Files, % SDPath . "\*", D 
	{
		If A_LoopFileAttrib contains H,R,S  ; Skip any file that is either H (Hidden), R (Read-only), or S (System).
    		continue  ; Skip this file and move on to the next one.

		If not RegExMatch(A_LoopFileName,"^(\d\d|advert|mp3)$")
		{
			errors .= "Ungültiger Ordnername: " A_LoopFileName " - im Hauptverzeichnis`n"
		}
	}

	Loop, Files, % SDPath . "\*", F
		errors .= "Ungültige Datei: " A_LoopFileName " - im Hauptverzeichnis`n"


	; next folder
	nextFolder(SDPath)
	; GuiControl, , NextFolder, % "Nächster Ordner: " . nextFolder(SDPath)
	GuiControl, , TargetFolder, % TargetFolderDropDown(SDPath,targetFolder)


	; skipped folder names
	empty := false
	Loop, 99
		If not FileExist(SDPath . "\" . Format("{1:02}",A_Index))
		{
			empty := true
		}
		Else If (empty) {
			errors .= "Nicht erreichbarer Ordner: " Format("{1:02}",A_Index) "`n"
		}

	if (StrLen(errors)) {
		GuiControl, Show, Fehler
		GuiControl, , Errors, % errors
		GuiControl, , Check, Fehler:
	} Else {
		GuiControl, ,Check, SD-Karte ist ok
		GuiControl, Hide, Errors
	}

	; Drive Space
	DriveSpaceFree, freeSpace, % SDPath

	DriveGet, cap, Capacity, % SDPath
	GuiControl, , SDSpace, % Format("{1:.2f}",freespace/1024) . " GB von " . Format("{1:.2f}",cap/1024) . " GB verfügbar "
	GuiControl, , SDSpaceProgress, % 100 - (freespace/cap) * 100
}

readFileList(AudioPath) 
{
	global recursive

	SB_SetText("Dateien lesen")
	LV_Delete()

	mode := "F"

	if (recursive)
		mode .= "R"

	Loop, Files, % AudioPath . "\*.mp3", % mode
	{
		LV_Add("", "kopieren", A_LoopFileName, id3read(A_LoopFileFullPath,021),id3read(A_LoopFileFullPath,026),A_LoopFileFullPath)
	}
	; auto-size
	LV_ModifyCol()
	; LV_ModifyCol(5, 0)

	SB_SetText("Bereit")
}

SaveIni:
	Gui, Submit, NoHide

	IniWrite, % AsAdmin, % iniPath, % "User", % "AsAdmin"
	IniWrite, % WithFilename, % iniPath, % "User", % "WithFilename"
	IniWrite, % Recursive, % iniPath, % "User", % "Recursive"
	IniWrite, % SmartRename, % iniPath, % "User", % "SmartRename"
	readFileList(AudioPath)
Return

GuiClose:
ExitApp

Recheck:
	checkSDCard(SDPath)
return

Restart:
Reload

#If !A_IsCompiled
F12::Reload

If A_Scriptname=id3read.ahk
	ExitApp

	
/*
Size ................................... (001): 166 KB
Element Type ........................... (002): MP3 audio format
Change Date ............................ (003): 12/03/2012 21:33
Creation ............................... (004): 12/03/2012 21:33
Last visit ............................. (005): 12/03/2012 21:33
Attributes ............................. (006): A
Recognized type ........................ (009): Audio
Owner .................................. (010): Voyager \ Janeway
Art .................................... (011): Music
Participants interpreters .............. (013): Individual Artist
Album .................................. (014): Album Name
Years .................................. (015): 1998
Genre .................................. (016): Other
Conductors ............................. (017): Conductor
Review ................................. (019): Not rated
Authors ................................ (020): Individual Artist
Title .................................. (021): Title of the song
Copyright .............................. (025): CopyRight
Track number ........................... (026): 1
Length ................................. (027): 00:00:06
Bitrate ................................ (028): 192 kbit / s
Protected .............................. (029): No
Computer ............................... (053): VOYAGER (this computer)
File Name .............................. (155): MP3-object Test.mp3
Released ............................... (173): No
Folder name ............................ (176): Desktop
Folder Path ............................ (177): D: \ system \ desktop
Folder ................................. (178): Desktop (C: \ System)
Path ................................... (180): D: \ WINDOWS \ Desktop \ MP3 object Test.mp3
Type ................................... (182): MP3 audio format
Link status ............................ (188): Unresolved
Encoded by ............................. (193): Encoded by (e.g. LAME)
Editor ................................. (195): Publisher
Subtitle ............................... (196): Subtitle
Album artist ........................... (217): Album Artist
Beats per minute ....................... (219): 120
Composers .............................. (220): Composer
Part of a set .......................... (224): 1
Sequence name .......................... (254): Subtitle
Approval Status ........................ (269): Not released

https://autohotkey.com/board/topic/83376-ahk-l-read-id3-tags-function/
*/

	
 	
id3read(filename,code)
{
	objShell := ComObjCreate("Shell.Application")
		
	SplitPath,filename , ename,edir

	oDir := objShell.NameSpace(eDir)
	oMP3 := oDir.ParseName(eName)
	  
	return oDir.GetDetailsOf(oMP3, code)
}
BoBo
Posts: 6564
Joined: 13 May 2014, 17:15

Re: Wie kann man Dateien zählen (und) formatieren?

22 Feb 2022, 18:30

Holla, sehr umfangreich. Ich habe sowas dann gerne zerlegt und als modul anschließend wieder #Include'd.
Textwüsten demotivieren mich. Ließ sich modular einfacher warten. Wer Editoren mit code-folding etc beherrscht sieht das wahrscheinlich weniger kritisch.

Liegen die zu löschenden 001,002,003... folder auf der selben Verzeichnisebene wie die 'Unantastbaren'?
Der :arrow: download zur SDCard zeigt zwar etwas ähnliches, nämlich: ..\advert, ..\mp3\xxxx.mp3
doch dort gibt es (noch?) keine nummerierten Ordner!?
Quelle: https://tonuino.de

Deine Wunschliste (sort of)
a) Ordner mit Zahlen am Anfang (also 001, 002, 003,...) löschen ("mp3" und "advert" nicht) - FileRemoveDir/Format()
b) Löschvorang per Button + Sicherheitsabfrage - Gui...
c) Vorgang, wenn gewünscht abbrechen - Process
d) Zählfunktion vorhandene Ordner/Dateien - Loop...
e) dynamischer Löschbutton abhängig von Speicherbelegung - GuiControl/DriveGetSpace/DriveSpaceFree

Zu...
b)
e)
argy
Posts: 4
Joined: 19 Feb 2022, 13:39

Re: Wie kann man Dateien zählen (und) formatieren?

23 Feb 2022, 16:16

Es geht bei dem Projekt darum, Daten auf eine SD-Karte zu kopieren, die alle eine Zahl vor den Datei-Namen bekommen (bspw wird mein lied.mp3 zu 001-MeinLied.mp3) und in Ordner abgelegt werden die ausschließlich Zahlen enthalten von 01 bis 99.

Auf der SD müssen zusätzlich 2 Order enthalten sein "mp3" und "advert".

Es wird aktuell geprüft, ob es die beiden Ordner ("mp3" und "advert") gibt und ob es andere Ordner gibt die mit bzw ohne Zahlen sind.
Dementsprechend werden Fehlermeldungen ausgegeben.

Bezüglich Dateien löschen bin ich mir nicht ganz sicher ob

Code: Select all

FileRemoveDir, %SDpath%\*.*, 1
funktioniert, denn ich willl ja nur die Ordner und Dateien auf der SD-Karte löschen möchte, aber den Pfad selbst (bspw E:) nicht.

Aktuell breche ich mir einen ab einen Loop zu bauen um die Dateien zu zählen. Ich finde aber meinen Denkfehler nicht...
Ich will einen Text einfügen

Code: Select all

Gui, Add, Text, gZaehlen, % count
wobei die Variable auf das hier zugreift:

Code: Select all

Zaehlen:
	count := 0
	Loop, Files, % SDPath . "\*", R 
	{
	    count++
	}
Ich habe die Abfrage schon mehrfach umgebaut und verschiedene Varianten versucht, aber es wird kein Text/Ergebnis ausgegeben.
Ist
% count
falsch?
BoBo
Posts: 6564
Joined: 13 May 2014, 17:15

Re: Wie kann man Dateien zählen (und) formatieren?

23 Feb 2022, 16:57

Code: Select all


SDPath := "E:"
Gui, Add, Text, gZaehlen vZaehlen,<hier die Zahl anzeigen>
Gui, Show,,% chr(160)
Sleep 1500

Zaehlen:
	count:=0
	Loop, Files,% SDPath . "\*.mp3", R 
	    count++
	GuiControl,, Zaehlen,% count		; schreibt werte in das Gui element, mit dem entsprechenden variablen bezeichner ('vZaehlen')
Return
Ungetested.
argy
Posts: 4
Joined: 19 Feb 2022, 13:39

Re: Wie kann man Dateien zählen (und) formatieren?

23 Feb 2022, 18:44

Danke für die schnelle Antwort.
Leider bekomme ich noch immer kein Ergebnis.

Hab schon den Pfad hart rein genommen um zu prüfen, ob es daran liegt, aber das scheint nicht der Fehler zu sein.
Den Text <hier die Zahl anzeigen> hab ich logischer weise weg gelassen.

Hat jemand noch eine andere Idee?
BoBo
Posts: 6564
Joined: 13 May 2014, 17:15

Re: Wie kann man Dateien zählen (und) formatieren?

24 Feb 2022, 01:38

Also bei mir geht das. Inhalte der Verzeichnisse 'advert'/'mp3' werden dabei nicht gezählt.

E:\ ..
advert\bla.txt
mp3\001.mp3
mp3\002.mp3
mp3\003.mp3
01\001.mp3
02\001.mp3
02\002.mp3

Ergebnis: 3/7
d)
User avatar
Gucky_87
Posts: 376
Joined: 03 Jul 2014, 05:09

Re: Wie kann man Dateien zählen (und) formatieren?

09 Mar 2022, 18:29

argy wrote:
19 Feb 2022, 13:53
Hallo. Ich bastle gerade an einen Projekt, bei dem Dateien auf eine SD-Karte geschrieben werden.
Es gibt dort (wenn alles korrekt ist) einen Order "mp3" und einen Ordner "advert".
In zusätzliche Ordner die nach dem Muster 001, 002, 003... aufgebaut sind werden dann Dateien rein kopiert.
Das hört sich nach dem DF-Player für Arduinos & Co an, kann das sein? ;)

Gucky.

Return to “Ich brauche Hilfe”

Who is online

Users browsing this forum: No registered users and 30 guests