Jump to content

Copying a directory with an exception listing


Recommended Posts

Hi All,

I'm having a bit of trouble with my script at the moment. The function that this is trying to accomplish is being able to copy a directory with exceptions, so if the file is an mp3 wma avi or whatever then it wont copy. Heres the func:

Func CopyFolder($SourceFolder, $DestinationDir)
    If Not FileExists($DestinationDir) Then DirCreate($DestinationDir)
    Local $Search = 0
    Local $File = 0
    Local $FileAttributes = 0
    $FullFilePath = ""
    $arraycounter = 0

    $Search = FileFindFirstFile($SourceFolder & "\*.*")

    While 1
        $ArrayCounter = $ArrayCounter + 1
        ReDim $FileListing[$FileListing[0]+$ArrayCounter]

        If $Search = -1 Then
            ExitLoop
        EndIf

        $File = FileFindNextFile($Search)
        If @error Then ExitLoop

        $FullFilePath = $SourceFolder & "\" & $File
        $FileAttributes = FileGetAttrib($FullFilePath)

        If StringInStr($FileAttributes,"D") Then
            $RefinedFolderName = $FullFilePath
            ;msgbox(0, "hm", "after setting $refinedfoldername to the same as $fullfilepath, its value is " & $RefinedFolderName)
            ;$RefinedFolderNamePosition = StringInStr($RefinedFolderName, "\", 0, -1)
            $RefinedFolderName = StringTrimLeft($RefinedFolderName, 12)
            ;msgbox(0, "hm", "after trimming left 12, its value is " & $RefinedFolderName)
            $RefinedFolderName = $RefinedFolderName & "\"
            ;msgbox(0, "hm", "after adding a slash onto $Refinedfoldername, its value is " & $RefinedFolderName)
            ;msgbox(0, "found a folder", "found a \ at " & $RefinedFolderNamePosition & " for string " & $RefinedFolderName)
            ;_FileWriteLog("log.txt", "Found a directory called " & $RefinedFolderName & " which we are copying to " & $DestinationDir & $RefinedFolderName)
            ;DirCreate($DestinationDir & $RefinedFolderName)
            CopyFolder($FullFilePath, $DestinationDir & "\" & $RefinedFolderName)
        Else
            ;LogFile($FullFilePath)
            ;_FileWriteLog("log.txt", "Found a file called " & $FullFilePath & " which we are copying to " & $DestinationDir & "\" & $RefinedFolderName)
            Select
                Case StringInStr($FullFilePath, ".mp3") > 0
                    _FileWriteLog($BackupLocation & "\log.txt", "Not copying " & $FullFilePath & " because it is an MP3 file and is an exception")
                    ;msgbox(0, "mp3", "found a \ at " & $RefinedFolderNamePosition & " for string " & $RefinedFolderName)
                Case StringInStr($FullFilePath, ".wma") > 0
                    _FileWriteLog($BackupLocation & "\log.txt", "Not copying " & $FullFilePath & " because it is an WMA file and is an exception")
                Case StringInStr($FullFilePath, ".avi") > 0
                    _FileWriteLog($BackupLocation & "\log.txt", "Not copying " & $FullFilePath & " because it is an AVI file and is an exception")
                Case Else
                    FileCopy($FullFilePath, $DestinationDir, 9)
                    _FileWriteLog($BackupLocation & "\log.txt","Copying " & $FullFilePath &" to " & $DestinationDir)
                    ;msgbox(0, "casing else", "found a \ at " & $RefinedFolderNamePosition & " for string " & $RefinedFolderName)
            EndSelect
        EndIf
        ;msgbox(0, "lol wat", "copying " & $FullFilePath & " to " & $DestinationDir & $RefinedFolderName)
        ;msgbox(0, "", $FullFilePath)
    WEnd

    FileClose($Search)
EndFunc

I've been nutting away at this for quite some time now...so its probably a bit overdone. If anyone could help I would be forever endebted... Additionally sorry for the dry reaching you're probably getting from reading my code :mellow:

Link to comment
Share on other sites

I made a stack based search function and PsaltyDS made a recursive version of it. You can just modify the section of the code which handles the file matching to get the type of matching behavior you need.

The thread is here.

Thanks for that man...but it doesnt recurse? arraydisplay just shows the root directory.

Link to comment
Share on other sites

Look closely. PsaltyDS' and mine also provide search results for subfolders depending on the parameters you provide it.

Setting depth to -1 yields the same results...heres the code

#include <Array.au3>
Dim $array
Opt("MustDeclareVars", 1)
;Put somewhere at the start of your script
;### STACK DEFINITION ###
Global $RESULT_MAX = 0xFFF ;maximum size of the returned array
Global $STACK_MAX = 0xFFF ;maximum size of the search stack
Global $STACK[$STACK_MAX] ;the search stack
$STACK[0] = 0 ;stack element counter
Func _Push($var) ;Utility function. DO NOT CALL
    If $STACK[0] < $STACK_MAX - 1 Then
        $STACK[0] += 1
        $STACK[$STACK[0]] = $var
    Else
        Return 1
    EndIf
    Return 0
EndFunc
Func _Pop() ;Utility function. DO NOT CALL
    If $STACK[0] > 0 Then
        $STACK[0] -= 1
        Return $STACK[$STACK[0] + 1]
    Else
        SetError(1)
    EndIf
    Return 0
EndFunc
;### END STACK DEFINITION ###
Global $start = TimerInit()
Global $result = _Search("c:\", "*.*", false, "", "", -1)
Global $time = TimerDiff($start)

_ArrayDisplay($result, "Time = " & _ConvertTime($time))

Func _ConvertTime($millis)
    Local $days = Int($millis / 86400000)
    $millis -= $days * 86400000
    Local $hours = Int($millis / 3600000)
    $millis -= $hours * 3600000
    Local $minutes = Int($millis / 60000)
    $millis -= $minutes * 60000
    Local $seconds = Int($millis / 1000)
    $millis -= $seconds * 1000
    Local $result = ""
    If $days > 0 Then
        $result &= $days & "d:"
    EndIf
    If $hours > 0 Then
        $result &= StringFormat("%.2d", $hours) & "h:"
    EndIf
    If $minutes > 0 Then
        $result &= StringFormat("%.2d", $minutes) & "m:"
    EndIf
    If $seconds > 0 Then
        $result &= StringFormat("%.2d", $seconds)
    Else
        $result &= "00"
    EndIf
    $result &= "." & StringFormat("%.3d", $millis) & "s"
    Return $result
EndFunc
;### SEARCH FUNCTION ###
;Returns array containing full path of matched files, with [0] containing the count of returned elements.
;
;$path        = start location of search
;
;$filter      = expression to use for file matching (e.g. *.txt)
;
;$directories = set to true if directories are to be included in the search results
;               Default set to True
;
;$fExclude    = attributes (look at FileGetAttrib) used to exclude files from search (e.g. if you want to skip read-only or hidden files)
;               Default set to empty string
;
;$dExclude    = attributes (look at FileGetAttrib) used to exclude folder from recursive search (e.g. if you want to skip searching system or hidden folders)
;               Default set to empty string
;
;$depth       = folder depth to limit search
;               Default set to -1
;
;               Values:
;                   0  -> current folder only
;                   n  -> search up to n folders deep
;                   -1 -> search in all subfolders
;
_Search("C:\*.*", "*.*", 1, "*.mp3", "", -1)
Func _Search($path, $filter, $directories = True, $fExclude = "", $dExclude = "", $depth = -1)
    ;check directory exists
    If FileExists($path) Then
        ;add "\" to end of path value if needed
        If StringCompare(StringRight($path, 1), "\") <> 0 Then
            $path &= "\"
        EndIf
        Local $result = ""
        Local $search, $fname, $attrib
        Local $array[2], $temp[2]
        $array[0] = $path
        $array[1] = $depth
        ;push initial search path to stack
        _Push($array)
        While 1
            ;pop next search path from stack
            $array = _Pop()
            ;exit if empty stack
            If @error == 1 Then
                ExitLoop
            EndIf
            ;search contents of current directory
            $search = FileFindFirstFile($array[0] & $filter)
            If $search <> -1 Then
                While 1
                    $fname = FileFindNextFile($search)
                    If @error == 1 Then
                        ExitLoop
                    EndIf
                    ;skip processing if directory is not included in search results
                    If @extended == 1 And Not $directories Then
                        ContinueLoop
                    EndIf
                    ;add file to results if it is not excluded from search
;                   $attrib = FileGetAttrib($fname)
;                   If _IsIncluded($attrib, $fExclude) Then
                        $result &= $array[0] & $fname & "|"
;                   EndIf
                WEnd
                FileClose($search)
            EndIf
            ;process subdirectories if within depth parameter
            If $array[1] <> 0 Then
                ;add subdirectories to stack if not excluded from search
                $search = FileFindFirstFile($array[0] & "*")
                While 1
                    $fname = FileFindNextFile($search)
                    If @error == 1 Then
                        ExitLoop
                    EndIf
                    ;add directory to stack if not excluded from search
                    If @extended == 1 Then
;                       $attrib = FileGetAttrib($fname)
;                       If _IsIncluded($attrib, $dExclude) Then
                            $temp[0] = $array[0] & $fname & "\"
                            $temp[1] = $array[1] - 1
                            _Push($temp)
;                       EndIf
                    EndIf
                WEnd
                FileClose($search)
            EndIf
        WEnd
        ;create return array
        If StringCompare(StringRight($result, 1), "|") == 0 Then
            $result = StringTrimRight($result, 1)
            $result = StringSplit($result, "|")
        Else
            $result = 0
        EndIf
        Return $result
    Else
        SetError(1, 0, 0)
    EndIf
EndFunc
;Func _IsIncluded($attrib, $exclude) ;Utility function. DO NOT CALL
;   For $i = 1 To StringLen($exclude)
;       If StringInStr($attrib, StringMid($exclude, $i, 1)) <> 0 Then
;           Return False
;       EndIf
;   Next
;   Return True
;EndFunc
;### END SEARCH FUNCTION ###
;msgbox(0, "wat", "cake")
_ArrayDisplay($array)
;msgbox(0, "wat", "cake")

Am I just being dense D:

Link to comment
Share on other sites

You should've read more, then you'd have found that there is corrected code at my latest post in that thread.

Here's one that works for me. it lists the contents of the C:\ drive.

#include <Array.au3>
Opt("MustDeclareVars", 1)
;Put somewhere at the start of your script
;### STACK DEFINITION ###
Global $STACK_MAX = 1;0xFF ;maximum size of the search stack
Global $STACK[$STACK_MAX] ;the search stack
$STACK[0] = 0 ;stack element counter
Func _Push($var) ;Utility function. DO NOT CALL
    If $STACK[0] > $STACK_MAX - 2 Then
        $STACK_MAX *= 2
        ReDim $STACK[$STACK_MAX]
    EndIf
    $STACK[0] += 1
    $STACK[$STACK[0]] = $var
    Return 1
EndFunc
Func _Pop() ;Utility function. DO NOT CALL
    If $STACK[0] > 0 Then
        $STACK[0] -= 1
        Return $STACK[$STACK[0] + 1]
    Else
        SetError(1)
    EndIf
    Return 0
EndFunc
;### END STACK DEFINITION ###

Global $result = _Search("c:\", "*.*", false, -1)
_ArrayDisplay($result, "Results")

;### SEARCH FUNCTION ###
;Returns array containing full path of matched files, with [0] containing the count of returned elements.
;
;PARAMETERS:
;
;$path        = start location of search
;
;$filter      = expression to use for file matching (e.g. *.txt)
;
;$directories = set to true if directories are to be included in the search results
;               Default set to True
;
;$depth       = folder depth to limit search
;               Default set to -1
;
;               Values:
;                   0  -> current folder only
;                   n  -> search up to n folders deep
;                   -1 -> search in all subfolders
;
;RETURN VALUE:
;
;Success:   Array of files and folders matching the search parameter.
;           [0] contains the count of matched elements.
;           matched folders end with "\"
;
;Failure:   Returns 0.
;           Sets @error to:
;               1   -> $path does not exist.
;               2   -> No matches found.
;
Func _Search($path, $filter, $directories = True, $depth = -1)
    ;check directory exists
    If FileExists($path) Then
        ;add "\" to end of path value if needed
        If StringCompare(StringRight($path, 1), "\") <> 0 Then
            $path &= "\"
        EndIf
        Local $result = ""
        Local $search, $fname, $attrib
        Local $array[2], $temp[2]
        $array[0] = $path
        $array[1] = $depth
        ;push initial search path to stack
        _Push($array)
        While 1
            ;pop next search path from stack
            $array = _Pop()
            ;exit if empty stack
            If @error == 1 Then
                ExitLoop
            EndIf
            ;search contents of current directory
            $search = FileFindFirstFile($array[0] & $filter)
            If $search <> -1 Then
                While 1
                    $fname = FileFindNextFile($search)
                    If @error == 1 Then
                        ExitLoop
                    EndIf
                    ;skip processing if directory is not included in search results
                    If @extended == 1 Then
                        If Not $directories Then
                            ContinueLoop
                        Else
                            $fname &= "\"
                        EndIf
                    EndIf
                    ;add file to results
                    $result &= $array[0] & $fname & "|"
                WEnd
                FileClose($search)
            EndIf
            ;process subdirectories if within depth parameter
            If $array[1] <> 0 Then
                ;add subdirectories to stack if not excluded from search
                $search = FileFindFirstFile($array[0] & "*")
                While 1
                    $fname = FileFindNextFile($search)
                    If @error == 1 Then
                        ExitLoop
                    EndIf
                    ;add directory to stack
                    $temp[0] = $array[0] & $fname & "\"
                    $temp[1] = $array[1] - 1
                    _Push($temp)
                WEnd
                FileClose($search)
            EndIf
        WEnd
        ;create return array
        If StringCompare(StringRight($result, 1), "|") == 0 Then
            $result = StringTrimRight($result, 1)
            $result = StringSplit($result, "|")
        Else
            $result = 0
            SetError(2, 0, 0)
        EndIf
        Return $result
    Else
        SetError(1, 0, 0)
    EndIf
EndFunc
;### END SEARCH FUNCTION ###

EDIT: The script you posted worked fine for me. I got the list of files in C:\.

EDIT2: Removed unneeded code from script.

Edited by omikron48
Link to comment
Share on other sites

You should've read more, then you'd have found that there is corrected code at my latest post in that thread.

Here's one that works for me. it lists the contents of the C:\ drive.

EDIT: The script you posted worked fine for me. I got the list of files in C:\.

EDIT2: Removed unneeded code from script.

<3 you omikron...probably be a bit better if I were a girl saying that tho. I'll go give this a test and see how it goes.

Link to comment
Share on other sites

Keep in mind, you'd still need to modify the code to get the matching behavior that you want.

I'd suggest using StringRegExp OR a combination of StringRight and StringCompare to test whether the filename you are processing ends with a certain file extension.

Can't help much with regular expressions since I don't get it much myself yet.

If StringCompare(StringRight($filename, 4), ".mp3") Then
    ;$filename is doesn't end in ".mp3"
EndIf
Edited by omikron48
Link to comment
Share on other sites

Keep in mind, you'd still need to modify the code to get the matching behavior that you want.

I'd suggest using StringRegExp OR a combination of StringRight and StringCompare to test whether the filename you are processing ends with a certain file extension.

Can't help much with regular expressions since I don't get it much myself yet.

If StringCompare(StringRight($filename, 4), ".mp3") Then
    ;$filename is doesn't end in ".mp3"
EndIf

Was thinking more along the lines of reading the entire directory to the array then when it comes to copying do something like this

Select
Case StringInStr($array[$counter], "*.mp3"
; dont copy
Case StringInStr($array[$counter], "*.avi"
; dont copy
Case StringInStr($array[$counter], "*.wma"
; dont copy
Case Else
FileCopy(blah blah blah)

EDIT: Problem with this being is that the $result is declared locally...moving that out to a dim so another function doesn't seem to work either. How would I read from the $result array in other functions?

Edited by lewwy
Link to comment
Share on other sites

Either store the return from _Search into a Global variable or pass the result into the other function.

Just using StringInStr isn't recommendable since there is nothing stopping anybody from making a folder with the name "music.mp3". It's a legal folder name. Anything contained there will match for StringInStr($array[$counter], "*.mp3").

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...