Somebody on the Something Awful forums asked me about my code that automatically organizes MP3’s I download, so here’s how it works…
I have a catch-all script that runs on my system all the time into which I insert various functions I write to automate tasks on my computer. In the main loop of this scrip I have a sub-loop which runs every 60 seconds like this:
$DelayBegin = TimerInit()
While 1
; Items in this loop only run every 60 seconds
If TimerDiff($DelayBegin) > 60000 Then
MoveMP3()
$DelayBegin = TimerInit()
EndIf
Sleep(100)
WEnd
This is pretty self-explanatory I think. Basically every time the difference between now and when $DelayBegin is initiated is greater than 60,000 milliseconds, the MoveMP3() function gets executed and then $DelayBegin gets reinitialized.
Before we get in to the MoveMP3() function, let me talk about a couple of the other functions which help MoveMP3() do it’s job. The first is GetExtProperty().
Func _GetExtProperty($sPath, $iProp)
Local $iExist, $sFile, $sDir, $oShellApp, $oDir, $oFile, $aProperty, $sProperty
$iExist = FileExists($sPath)
If $iExist = 0 Then
SetError(1)
Return 0
Else
$sFile = StringTrimLeft($sPath, StringInStr($sPath, "\", 0, -1))
$sDir = StringTrimRight($sPath, (StringLen($sPath) - StringInStr($sPath, "\", 0, -1)))
$oShellApp = ObjCreate("shell.application")
$oDir = $oShellApp.NameSpace($sDir)
$oFile = $oDir.Parsename($sFile)
If $iProp = -1 Then
Local $aProperty[35]
For $i = 0 To 34
$aProperty[$i] = $oDir.GetDetailsOf($oFile, $i)
Next
Return $aProperty
Else
$sProperty = $oDir.GetDetailsOf($oFile, $iProp)
If $sProperty = "" Then
Return 0
Else
Return $sProperty
EndIf
EndIf
EndIf
EndFunc
Now, I didn’t write GetExtProperty(), but for the life of me I can’t remember where I found it. If anyone knows where it came from, I’d be glad to point others to that place. I do know the notes credit the author Simucal (simucal[at]gmail.com)…
Anway, this function takes a file path and then the index to the extended property you want to get and returns the value of that field. This index seems to vary between the various versions of Windows, so you’ll have to do some testing on your target installations to see which index returns the values you want. To aid in your testing, if you give it a -1 for the index it will return a 1-dimensional array containing all of the properties.
The next function I use is _FileListToArrayEx().
Func _FileListToArrayEx($sPath, $sFilter = '*.*', $iFlag = 0, $sExclude = '', $iRecurse = False)
If Not FileExists($sPath) Then Return SetError(1, 1, '')
If $sFilter = -1 Or $sFilter = Default Then $sFilter = '*.*'
If $iFlag = -1 Or $iFlag = Default Then $iFlag = 0
If $sExclude = -1 Or $sExclude = Default Then $sExclude = ''
Local $aBadChar[6] = ['\', '/', ':', '>', '< ', '|']
$sFilter = StringRegExpReplace($sFilter, '\s*;\s*', ';')
If StringRight($sPath, 1) <> '\' Then $sPath &= '\'
For $iCC = 0 To 5
If StringInStr($sFilter, $aBadChar[$iCC]) Or _
StringInStr($sExclude, $aBadChar[$iCC]) Then Return SetError(2, 2, '')
Next
If StringStripWS($sFilter, 8) = '' Then Return SetError(2, 2, '')
If Not ($iFlag = 0 Or $iFlag = 1 Or $iFlag = 2) Then Return SetError(3, 3, '')
Local $oFSO = ObjCreate("Scripting.FileSystemObject"), $sTFolder
$sTFolder = $oFSO.GetSpecialFolder(2)
Local $hOutFile = @TempDir & $oFSO.GetTempName
If Not StringInStr($sFilter, ';') Then $sFilter &= ';'
Local $aSplit = StringSplit(StringStripWS($sFilter, 8), ';'), $sRead, $sHoldSplit
For $iCC = 1 To $aSplit[0]
If StringStripWS($aSplit[$iCC], 8) = '' Then ContinueLoop
If StringLeft($aSplit[$iCC], 1) = '.' And _
UBound(StringSplit($aSplit[$iCC], '.')) - 2 = 1 Then $aSplit[$iCC] = '*' & $aSplit[$iCC]
$sHoldSplit &= '"' & $sPath & $aSplit[$iCC] & '" '
Next
$sHoldSplit = StringTrimRight($sHoldSplit, 1)
If $iRecurse Then
RunWait(@ComSpec & ' /c dir /b /s /a ' & $sHoldSplit & ' > "' & $hOutFile & '"', '', @SW_HIDE)
Else
RunWait(@ComSpec & ' /c dir /b /a ' & $sHoldSplit & ' /o-e /od > "' & $hOutFile & '"', '', @SW_HIDE)
EndIf
$sRead &= FileRead($hOutFile)
If Not FileExists($hOutFile) Then Return SetError(4, 4, '')
FileDelete($hOutFile)
If StringStripWS($sRead, 8) = '' Then SetError(4, 4, '')
Local $aFSplit = StringSplit(StringTrimRight(StringStripCR($sRead), 1), @LF)
Local $sHold
For $iCC = 1 To $aFSplit[0]
If $sExclude And StringLeft($aFSplit[$iCC], _
StringLen(StringReplace($sExclude, '*', ''))) = StringReplace($sExclude, '*', '') Then ContinueLoop
Switch $iFlag
Case 0
If StringRegExp($aFSplit[$iCC], '\w:\\') = 0 Then
$sHold &= $sPath & $aFSplit[$iCC] & Chr(1)
Else
$sHold &= $aFSplit[$iCC] & Chr(1)
EndIf
Case 1
If StringInStr(FileGetAttrib($sPath & '\' & $aFSplit[$iCC]), 'd') = 0 And _
StringInStr(FileGetAttrib($aFSplit[$iCC]), 'd') = 0 Then
If StringRegExp($aFSplit[$iCC], '\w:\\') = 0 Then
$sHold &= $sPath & $aFSplit[$iCC] & Chr(1)
Else
$sHold &= $aFSplit[$iCC] & Chr(1)
EndIf
EndIf
Case 2
If StringInStr(FileGetAttrib($sPath & '\' & $aFSplit[$iCC]), 'd') Or _
StringInStr(FileGetAttrib($aFSplit[$iCC]), 'd') Then
If StringRegExp($aFSplit[$iCC], '\w:\\') = 0 Then
$sHold &= $sPath & $aFSplit[$iCC] & Chr(1)
Else
$sHold &= $aFSplit[$iCC] & Chr(1)
EndIf
EndIf
EndSwitch
Next
If StringTrimRight($sHold, 1) Then Return StringSplit(StringTrimRight($sHold, 1), Chr(1))
Return SetError(4, 4, '')
EndFunc ;==>_FileListToArrayEx
This function by SmOke_N of the AutoIt forums returns a list of files in a folder and can be used with wildcards as you can see in the MoveMP3() function.
Func MoveMP3()
; Indexes for file properties returned by GetExtProperty
$idxArtist = 13
$idxAlbum = 14
$idxTrack = 26
$idxName = 21
; Source directory
$source_dir = "C:\Users\Therms\Documents\allTunes\My Music"
; Destination root (include trailing slash)
$mp3_dest = "Y:\"
; If destination not available then we quit
If Not FileExists($mp3_dest) Then Return
; Get list of new mp3 files
$mp3_source = _FileListToArrayEx($source_dir, "*.mp3", 0, "", True)
; Check if any mp3's are there
If $mp3_source = "" Then
Return
EndIf
If $mp3_source[0] = 1 Then
If StringInStr(FileGetAttrib($mp3_source[1]), "D") Then
$ret = DirRemove($mp3_source[1], 1)
Return
EndIf
EndIf
; Get track info and move files appropriately
Dim $fileinfos[4][$mp3_source[0]]
For $i = 1 To $mp3_source[0]
$artist = StringStripWS(_GetExtProperty($mp3_source[$i], $idxArtist), 3)
$album = StringStripWS(_GetExtProperty($mp3_source[$i], $idxAlbum), 3)
$track = StringStripWS(_GetExtProperty($mp3_source[$i], $idxTrack), 3)
If Int($track) < 10 Then $track = "0" & $track
$trackname = StringStripWS(_GetExtProperty($mp3_source[$i], $idxName), 3)
$dest_path = StringFormat('%s%s\\%s\\%s - %s.mp3', $mp3_dest, $artist, $album, $track, $trackname)
$result = FileMove($mp3_source[$i], $dest_path, 8)
FileModTimeNow($dest_path)
Next
EndFunc ;==>MoveMP3
Hopefully this helps you out if you’d like to do something similar.
I’m interested in the script, but it’s almost impossible to read it because of the broken html tags. Could you re-post the code without tags, please? Thanks
Hmm, I don’t know what happened with those tags…
Give me a few minutes and I’ll fix it up.
Ok, I somewhat fixed it. See my note at the beginning of the post now.
Bravo, que frase…, el pensamiento excelente