With considerable assistance, I have developed a batch script that, for each file in a drive or folder, prints file date, time, size, hash, and path on a single line. Problem: the batch script uses nested FOR loops that may be the cause of the script’s very slow processing.
I had previously tried to devise a PowerShell command to the same end. The command I developed was as follows:
This command seemed OK for getting the hash, at least, but as I recall it mostly neglected the other desired bits of file information (e.g., size). Its other problem was that it seemed to abort whenever it failed to find a file that it expected to find. That was problematic. Over the hours that it may take to hash a large drive, some files are likely to change or move.
I’m no PowerShell programmer. I can probably come to understand a relatively simple (or at least not absurdly long and/or complex) PowerShell solution. Batch is more familiar to me; I would also welcome insights into the slowness of that batch script.
While you could do this on one line a script is going to be easier to read and manage. You can use the power of custom objects to get your desired output.
I have assigned it all to a variable which could be displayed in the console, or output to a CSV. But you could output the objects to the pipeline for further processing, or export them one at a time to a CSV file.
If you excuse me being a bit pedantic: no, you couldn’t call it at @Goldfish because that’s not a valid variable name. $Goldfish would be OK though :).
One object per hashed file.
[PSCustomObject] is a type accelerator and is used for creating an object of type PSCustomObject. I recommend reading the article @Olaf linked for detailed information on that subject.
Suffice to say we are creating an object with three properties. We get two of those properties from the output of Get-FileHash (Get-FileHash outputs an object of type FileHash and Path and Hash are properties of that object), and we get the Length property from the FileInfo object representing the current file.
Implicitly, yes. PowerShell outputs it to the console because it’s not been told what to do with it. However, you could pipe it to another cmdlet such as Export-Csv, or Out-File, or Format-List.
Thanks, Matt. As I know, once a person gets familiar with something, it can be difficult to remember what it was like to know nothing about it.
Some questions, seeking brief answers as your time permits:
Short of checking the lists every time you want to define a variable, how can you know if your chosen variable is already a system variable? I guess you just get familiar with the fact that variables beginning with “root” or “file” are not taken?
Why doesn’t it say, Get-ChildItem -Path $rootPath -Recurse -File? If the provision of a valid path makes it obvious, why would anyone ever include -Path?
Why would someone use ForEach-Object if (as it appears) foreach does the same thing?
Where or how is the $file.FullName variable defined? Why include a period in its name?
I suspect the answer to the preceding question will also shed light on $hash.Path etc.
You’re right - that PSCustomObject article is definitely good for “detailed information on that subject.” The suggestion to start there was like handing someone a textbook titled, “Statistical Procedures for Population Analysis,” when they merely asked whether Ohio contains more resettled refugees than Michigan.
Sorry, Crazy Doug, these responses don’t address my questions.
Your profile describes you as a long-time IT pro. I appreciate that that technical article on PowerShell is easy for you - requiring, you say, only ten minutes to read and understand what you rightly describe as its “tons of information.” As I said before, I realize that an expert in a subject may have no concept of what it is like to be a beginner.
You’re certainly entitled to your opinions about the PSCustomObject article, and so forth. But if you could restrain yourself from preaching at me, and just answer the specific questions I have posed, that would actually be helpful.
If you use a decent IDE, like VSCode, it will warn you.
Best practice, especially when writing code that others will read, is to be as verbose as possible and I should have included the parameter name. However, it’s not always necessary to include the parameter name. See Get-Help about_ Parameters.
They are different. This is a common ‘gotcha’ that you need to be aware of:
As the foreach loop iterates through the collection of files in $fileList the file currently being worked on is assigned to the variable $file. FullName is a property of FileInfo objects and one way of accessing that property’s value is using the dot notation.
Yes, Path and Hash are properties of a FileHashInfo object. Get-FileHash returns an object of type FileHashInfo, this object is referenced by the variable $hash.
Thank you again for your kind help, Matt. If I make a start in PowerShell, I will begin with the study resources you’ve recommended.
I have compiled much of this information into a blog post. As described there, my present impression is that I will have to devote considerable study to reach a point of using PowerShell effectively. This is the impression that has kept me using batch.