Jump to content
Sign in to follow this  
rumour

Load similar filenames into an array

Recommended Posts

rumour

Hi all!

This should be an easy one for all of you programmers out there...

I have a directory of .pdf files, each with a name and a series number, i.e.:

file_01.pdf

file_02.pdf

text_01.pdf

text_02.pdf

text_03.pdf

document_01.pdf

document_02.pdf

I'm trying to build an array of each set of files, i.e.:

array1 = file_01.pdf, file_02.pdf

array2 = text_01.pdf, text_02.pdf, text_03.pdf

array3 = document_01.pdf, document_02.pdf

The code I've written works until I reach the last file in the directory. I'm running into a problem with the line...

$comp2=StringSplit($bdOFL[$y+1],"_")

...it breaks when $y + 1 goes greater than the number of files in the the directory.

Here's the code:

#include <file.au3>
#include <string.au3>
#include <array.au3>

HotKeySet("^!x", "MyExit"); hotkey to exit = CTRL+ALT+X

$bdSD = "C:\Practice Folder\"

$bdOFL = _FileListToArray($bdSD,"*.pdf"); build an array of files in the source directory
$x=$bdOFL[0]; number of files in source directory
$y = 1; current position counter

While $y < $x+1
    Dim $bdFL[100]; unlikely to group more than 100 files
    $z=1; number of files in current grouping
    Do 
        $bdFL[$z-1]=$bdOFL[$y]      
        $comp1=StringSplit($bdOFL[$y],"_"); loads filename up to the underscore
        $comp2=StringSplit($bdOFL[$y+1],"_"); loads filename up to the underscore
        $z=$z+1
        $y=$y+1
    Until $comp1[1]<>$comp2[1]; are the filenames up to the underscore different?
    ReDim $bdFL[$z-1]
    _ArrayDisplay($bdFL,"$bdFL"); debug code
WEnd

Func MyExit()
    Exit 
EndFunc

Any suggestions? Thanks in advance!

Brian

Share this post


Link to post
Share on other sites
PsaltyDS

Why not just use better wildcard patterns and get them straight to the arrays?

#include <file.au3>
#include <array.au3>

Global $bdSD = "C:\Practice Folder\"

$avFileList = _FileListToArray($bdSD, "file_*.pdf")
$avTextList = _FileListToArray($bdSD, "text_*.pdf")
$avDocList = _FileListToArray($bdSD, "document_*.pdf")
$TotalFiles = $avFileList[0] + $avTextList[0] + $avDocList[0]

If MsgBox(64 + 4, "Results", "There are a total of " & $TotalFiles & " selected .pdf files." & @CRLF & _
        "file_*.pdf files:  " & $avFileList[0] & @CRLF & _
        "text_*.pdf files:  " & $avTextList[0] & @CRLF & _
        "document_*.pdf files:  " & $avDocList[0] & @CRLF & _
        "Do you want to see them listed?") = 6 Then
    _ArrayDisplay($avFileList, "file_*.pdf files")
    _ArrayDisplay($avTextList, "text_*.pdf files")
    _ArrayDisplay($avDocList, "document_*.pdf files")
EndIf

:)


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites
rumour

Well...perhaps I was too generic with my problem statement. The working directory has lots of different files with different names. They all take the format of name datestamp_##.pdf, but I don't think setting up standing wildcards is what I want to do. Here's a list of actual files in the working directory:

ATT 20070405_1.PDF

ATT 20070405_2.PDF

ATT 20070405_3.PDF

Chase MC 20070412_1.PDF

Chase MC 20070412_2.PDF

Dish Network 20070511_1.PDF

Dish Network 20070511_2.PDF

GECU 20070331_1.PDF

GECU 20070331_2.PDF

GPFCU 20070331_1.PDF

GPFCU 20070331_2.PDF

Here's the Menu_1.PDF

Here's the Menu_2.PDF

Here's the Menu_3.PDF

Here's the Menu_4.PDF

Here's the Menu_5.PDF

JCAD Notice of Appraised Value 20070423_1.PDF

JCAD Notice of Appraised Value 20070423_2.PDF

LPM 20070508_1.PDF

LPM 20070508_2.PDF

OSB 20070405_1.PDF

OSB 20070405_2.PDF

OSB 20070405_3.PDF

OSB 20070405_4.PDF

OSB 20070505_1.PDF

OSB 20070505_2.PDF

OSB 20070505_3.PDF

OSB 20070505_4.PDF

Save the Earth While Saving Some Money_1.PDF

Save the Earth While Saving Some Money_2.PDF

Save the Earth While Saving Some Money_3.PDF

Save the Earth While Saving Some Money_4.PDF

Trailer Title_1.PDF

Trailer Title_2.PDF

Trailer Title_3.PDF

This is a partial list. The purpose of my original script is to form arrays, which will be used to make delimited strings, which will be fed to a program to combine each group of .pdfs into a single .pdf. So, once I process these files, I will eventually re-fill the directory with new files (with different file names).

Sorry for the confusion.

Brian

Share this post


Link to post
Share on other sites
weaponx

This will be tricky since some files in your examples have timestamps and some don't.

Share this post


Link to post
Share on other sites
Zedna

Use _FileListToArray($bdSD, "*.pdf")

to have all files in one array.

Then sort this array: _ArraySort()

Now go throug tjat array and test whether name without last character is the same as previous array item

If YES then it's one group else start new group.

Share this post


Link to post
Share on other sites
weaponx

I threw this together for you, it only matches filenames if the datestamps AND the title match, just run it in the folder with all of your files

#include <Array.au3>

; Shows the filenames of all files in the current directory.
$search = FileFindFirstFile("*.PDF")

Dim $ARRAY[1]
$last = ""
Dim $X = 0

; Check if the search was successful
If $search = -1 Then
    MsgBox(0, "Error", "No files/directories matched the search pattern")
    Exit
EndIf

;Loop until error
While 1
    $file = FileFindNextFile($search) 
    If @error Then ExitLoop
    
    ;Return portion of file name before underscore
    $splitfilename = StringSplit ( $file, "_" )
    
    ;If beginning of filename matches beginning of last filename
    If $splitfilename[1] = $last Then 
        
        ;Concat current filename to last array element with comma
        $ARRAY[Ubound($ARRAY) - 1] &= "," & $file
    
    ;If no match, create a new array element
    Else        
        ;Manually assign first element, due to ARRAYADD skipping element zero
        If $X = 0 Then
            $ARRAY[$X] = $file
        Else
            _ArrayAdd( $ARRAY, $file)
        EndIf
        $X += 1
    EndIf
    
    ;Update last file name
    $last = $splitfilename[1]
WEnd

;Display array
_ArrayDisplay ( $ARRAY, "ARRAY CONTENTS")

; Close the search handle
FileClose($search)

Share this post


Link to post
Share on other sites
rumour

Thanks weaponx!

I tried your code. Slight modification, and viola! While it doesn't do what I was originally attempting (separate array for each set of files), I can use it's output quite easily.

Thanks again.

Brian

Share this post


Link to post
Share on other sites
PsaltyDS

Well...perhaps I was too generic with my problem statement. The working directory has lots of different files with different names. They all take the format of name datestamp_##.pdf, but I don't think setting up standing wildcards is what I want to do. Here's a list of actual files in the working directory:

This is a partial list. The purpose of my original script is to form arrays, which will be used to make delimited strings, which will be fed to a program to combine each group of .pdfs into a single .pdf. So, once I process these files, I will eventually re-fill the directory with new files (with different file names).

Sorry for the confusion.

Brian

I saved your list to Test_1.txt and ran this on it:

#include <file.au3>

$hFile = FileOpen("Test_1.txt", 0)
While 1
    $Line = FileReadLine($hFile)
    If @error Then ExitLoop
    _FileCreate("C:\Temp\" & $Line)
WEndoÝ÷ Ù*«ÞÊ«{¶X¬¶ßW¬p´÷dÞh¦V²Â+aN¬~éܶ*'+Þ³*.jX¬¶è­ë§«~)^©®-²Ú-ë§uêìrÞªê-ªê-jëh×6#include <file.au3>
#include <array.au3>

$TargetDir = "C:\Temp"
$avNameList = _ListPDFs($TargetDir)
_ArrayDisplay($avNameList, "List of PDF name roots")

Func _ListPDFs($sDir)
    Local $avFiles = _FileListToArray($sDir, "*.pdf", 1)
    _ArraySort($avFiles, 0, 1) ; Sort ascending from [1]
    Local $n
    For $n = 1 To $avFiles[0]
        $avFiles[$n] = StringLeft($avFiles[$n], StringInStr($avFiles[$n], "_"))
    Next
    For $n = $avFiles[0] To 1 Step - 1
        If $avFiles[$n] = "" Or $avFiles[$n] = $avFiles[$n - 1] Then _ArrayDelete($avFiles, $n)
    Next
    $avFiles[0] = UBound($avFiles) - 1
    Return $avFiles
EndFunc   ;==>_ListPDFs

Hope that helps.

:)


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites
weaponx

Glad I could help. Also there is no way to create arrays dynamically, at runtime, so you have to have an array with each element being a CSV string.

Share this post


Link to post
Share on other sites
PsaltyDS

Also there is no way to create arrays dynamically, at runtime, so you have to have an array with each element being a CSV string.

Well, not that it's applicable to this topic, but that's actually one of the few useful things I can imagine about arrays in arrays. You can use _ArrayAdd() to add elements to a single array, and each of those elements can contain a copy of a dynamic array from something like _FileReadToArray() or IniReadSection(). You can iterate through the parent array, copying out each element to a working array.

There are, of course, speed and resource penalties for doing it that way... but it can be done. This demo reads the contents of all .txt files in a directory to an array, then saves the arrays in an array. After a prompt, it reads each array out of the parent array and displays them:

#include <array.au3>
#include <file.au3>

Global $avFiles[1] = [0]

_TxtArrayAddDir(@DocumentsCommonDir)

If MsgBox(32 + 4, "Question", "Do you want to see the contents of all " & $avFiles[0] & " .txt files?") = 6 Then
    _TxtArrayDisplay()
EndIf

; Add FileReadToArray arrays of .txt files to the $avFiles array
Func _TxtArrayAddDir($sDir)
    Local $FileName, $avFileList, $avWorking
    For $FileName In _FileListToArray($sDir, "*.txt", 1)
        If IsNumber($FileName) Then
            $avFiles[0] = $avFiles[0] + $FileName ; Save count
            ContinueLoop
        EndIf
        _FileReadToArray($sDir & "\" & $FileName, $avWorking)
        $avWorking[0] = $sDir & "\" & $FileName
        _ArrayAdd($avFiles, $avWorking)
    Next
EndFunc   ;==>_TxtArrayAddDir

; List contents of each array in the $avFiles array
Func _TxtArrayDisplay()
    Local $avWorking, $FileName
    For $avWorking In $avFiles
        If Not IsArray($avWorking) Then ContinueLoop
        $FileName = $avWorking[0]
        $avWorking[0] = UBound($avWorking) - 1
        _ArrayDisplay($avWorking, $FileName)
    Next
EndFunc   ;==>_TxtArrayDisplay

:)


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites
rumour

PsaltyDS - one of my next steps was to build a filename for each group of consolidated files - obviously I'd use the left part of the filename up to the underscore. I was going to play around with this, but you've basically solved that for me - thanks!

Share this post


Link to post
Share on other sites
rumour

Actually, I have another question for PsaltyDS and Zedna - I noticed that both of you use or suggest _ArraySort(). It seems that _FileListToArray() will build a sorted array (I assume because windows lists files alphabetically). Is there a reason to add _ArraySort(), or a time when you can't depend on _FileListToArray() to build a sorted array?

Brian

Share this post


Link to post
Share on other sites
PsaltyDS

Actually, I have another question for PsaltyDS and Zedna - I noticed that both of you use or suggest _ArraySort(). It seems that _FileListToArray() will build a sorted array (I assume because windows lists files alphabetically). Is there a reason to add _ArraySort(), or a time when you can't depend on _FileListToArray() to build a sorted array?

Never, never, never trust a Microsoft product to do something consistent and logical like always listing the files in order...

:)


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites
rumour

Never, never, never trust a Microsoft product to do something consistent and logical like always listing the files in order...

:)

Touche - I'll update my code appropriately.

Thanks again for your help.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×