Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# Find all files in subdirectories modified within the last 5 days

Tags:

f#

I am fairly new to F# so please be gentle. I am trying to write code in a functional style to look through a directory (and subdirectories) for all files modified within the last 5 days and then do something with those files (at the moment that is just to write the name to the console).

The code I have is:

open System.IO

let rec getAllFiles dir pattern =
    seq { yield! Directory.EnumerateFiles(dir, pattern)
          for d in Directory.EnumerateDirectories(dir) do
              yield! getAllFiles d pattern }

let printMe x = printfn "%A" x

let hasChangedRecently fileName =
    let myFile = System.IO.FileInfo(fileName)
    let f myFile = function
    | myFile when myFile.LastWriteTime >= System.DateTime.Parse "10-04-2015" -> printMe MyFile.Name
    | _ -> ()

    f fileName

[<EntryPoint>]
let main argv =
    getAllFiles @"c:\temp" "*.xml"
    |> Seq.iter hasChangedRecently

    System.Console.ReadKey() |> ignore
    0 // return an integer exit code

It is all going wrong in the hasChangedRecently block.

The errors are:

myFile.LastWriteTime
Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved.

MyFile.Name
The namespace or module 'MyFile' is not defined

|> Seq.iter hasChangedRecently
Type mismatch. Expecting a
string -> unit    
but given a
string -> 'a -> unit    
The type 'unit' does not match the type ''a -> unit'

I am quite sure these are basic errors but would sincerely appreciate some guidance.

like image 734
PeterB Avatar asked Oct 26 '25 04:10

PeterB


1 Answers

I would change the hasRecentlyChanged to be string -> bool function and filter the files with it, then have a separate function to print the files.

let hasChangedRecently fileName =
    let myFile = System.IO.FileInfo(fileName)
    myFile.LastWriteTime >= System.DateTime.Parse "10-04-2015"

let printFile file =
    printfn "%s" file

and in main:

getAllFiles @"c:\temp" "*.xml"
|> Seq.filter hasChangedRecently
|> Seq.iter printFile

Also, if you want, you can avoid getAllFiles been recursive by using SearchOption.AllDirectories built into .NET:

Directory.EnumerateFiles(dir, pattern, SearchOption.AllDirectories)
like image 79
DaveShaw Avatar answered Oct 28 '25 03:10

DaveShaw



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!