Last active
February 4, 2020 18:27
-
-
Save tallpeak/53d729a40181c25380040b5663622320 to your computer and use it in GitHub Desktop.
Compare directories
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// compare.fsx | |
// for each file, get name-only and hash. | |
// eliminate files with matching hashes | |
// display differences for files with the same name-only | |
// display files not found in destination by name-only | |
// display files not found in source by name-only | |
let srcDir = @"C:\temp\xxxx_ProductionInitializeDeploymentScripts" | |
let destDir = @"C:\Users\[myusername]\Source\Repos\[DH-ODP]\Main\Scripts" | |
open System | |
open System.IO | |
open System.Security.Cryptography | |
// synchronous file hashing | |
let hashFile f = | |
use fs = new FileStream(f, FileMode.Open) | |
use hashFunction = new SHA1Managed() | |
hashFunction.ComputeHash fs |> Convert.ToBase64String | |
let rec listFiles dir = seq { | |
yield! Directory.GetFiles(dir) | |
for subdir in Directory.GetDirectories(dir) do | |
yield! listFiles subdir | |
} | |
let hashFiles sq = seq { | |
for f in sq do | |
yield (hashFile f, (f , IO.DirectoryInfo(f).Name ) ) | |
} | |
let destFiles = listFiles destDir |> hashFiles |> Map | |
let srcFiles = listFiles srcDir |> hashFiles |> Map | |
// buggy | |
//printfn "Eliminating matching files from destination collection" | |
// for kv in srcFiles do | |
// destFiles <- destFiles.Remove kv.Key | |
// printfn "%s" (snd kv.Value) | |
// printfn "Eliminating matching files from source collection" | |
// for kv in destFiles do | |
// srcFiles <- srcFiles.Remove kv.Key | |
// printfn "%s" (snd kv.Value) | |
// let's make this a bit shorter: | |
// let destFilesUniq = Map.fold (fun mp k v -> Map.remove k mp) destFiles srcFiles | |
// let srcFilesUniq = Map.fold (fun mp k v -> Map.remove k mp) srcFiles destFiles | |
// a set-subtraction operator for Map: | |
let inline (-) (dMap:Map<'k,'v>) (sMap:Map<'k,'v> ) = | |
Map.fold (fun mp k _ -> Map.remove k mp) dMap sMap | |
let destFilesUniq = destFiles - srcFiles | |
let srcFilesUniq = srcFiles - destFiles | |
printfn "Uniq in source: %d" srcFilesUniq.Count | |
printfn "Uniq in destination: %d" destFilesUniq.Count | |
destFilesUniq | |
|> Seq.map (fun kv -> kv.Value |> fst ) | |
|> Seq.iter (printfn "%s") | |
// need to move the filename to the key of the tuple. No longer need hashes, since we deleted all filesnames that match by hash: | |
let srcByFilename = | |
srcFilesUniq | |
|> Map.toList | |
|> List.map (fun (h,(fullname,nm)) -> (nm,fullname)) | |
|> Map | |
let destByFilename = | |
destFilesUniq | |
|> Map.toList | |
|> List.map (fun (h,(fullname,nm)) -> (nm,fullname)) | |
|> Map | |
let inSrcOnly = srcByFilename - destByFilename | |
let inDestOnly = destByFilename - srcByFilename | |
printfn "\nIn source only (%s):" srcDir | |
inSrcOnly |> Seq.iter (fun kv-> printfn "%s" kv.Value) | |
printfn "\nIn destination only (%s):" destDir | |
inDestOnly |> Seq.iter (fun kv-> printfn "%s" kv.Value) | |
let differing = | |
query { for kv in srcByFilename do | |
where ( Option.isSome(destByFilename.TryFind kv.Key) ) | |
select (kv.Value, (destByFilename.Item kv.Key) ) | |
} | |
differing |> Seq.length |> printfn "count of differing files: %d" | |
differing | |
|> Seq.iter (fun (src,dst) -> printfn "%s\t%s" src dst ) | |
let repl (s:string) = s.Replace("C:\\temp", @"\\[servername]\Shared\Prism\ODP\Projects\CDLZ_30_PRD") | |
let sb = System.Text.StringBuilder() | |
differing | |
|> Seq.iter (fun (src,dst) -> sb.Append (sprintf " \"%s\" \"%s\"\n" (repl src) dst) |> ignore ) | |
printfn "%s" (sb.ToString()) | |
open System.Windows.Forms | |
Clipboard.SetText(sb.ToString()) | |
let mapValuesToClipboard (mp:Map<string,string>) = | |
let sb = System.Text.StringBuilder() | |
mp |> Seq.iter (fun kv -> sb.Append (sprintf "%s\n" kv.Value) |> ignore) | |
Clipboard.SetText(sb.ToString()) | |
let mapValuesToClipboard2 (mp:Map<string,string>) = | |
let ar = mp |> Map.toArray |> Array.map snd | |
let str = String.Join("\n",ar) | |
Clipboard.SetText(str) | |
inSrcOnly |> mapValuesToClipboard | |
inDestOnly |> mapValuesToClipboard |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment