My code will not write "No files to process" - powershell

My code will not display "No files to process" on the screen. It is supposed to count the files in a directory and if there are none then it should display "No files to process" and then exit.
# Function Measure, counts files to see if there are any to process.
Function Measure
{
$Measure = ( Get-ChildItem C:\temp\BDMDump\ | Measure-Object ).Count
If ($Measure = "0")
{Write-Host "No files to process"|Exit}
else
{Write-Host "There are files to process.."}
}
I expect to see "No files to process".

There are 4 issues here:
You are using the '=' which is only used for assignment. Use '-eq for comparison.
You are enclosing your integer with quotes, converting it into a string. Just remove the quotes.
As mentioned by ineedalife, you're piping to Exit. You should instead use a semi-colon and the return keyword ; return to exit the function. Even this is probably not needed if the function doesn't do anything else.
You are trying to use "Measure" as the function's name. This is an alias to Measure-Object! Simply change the name to something else, like "Measure-Files"
Additionally, you could remove | Measure-Object because the object System.IO.FileInfo which is returned by Get-ChildItem already has a "Count" method.
Here's a revised copy of your code with all the changes:
Function Measure-Files {
$Measure = Get-ChildItem "C:\temp\BDMDump\"
If ($Measure.Count -eq 0)
{ Write-Host "No files to process"; return }
else
{ Write-Host "There are files to process.." }
}

There are 3 problems
1. Exit can not be Piped to. If you want to exit the session useExit-PSSession this will close the window.
2. "Is equal to" should be changed from = to -eq
3. "0" should be changed to 0 as it is an integer
If ($Measure -eq 0)
{Write-Host "No files to process"|Exit-PSSession}
else
{Write-Host "There are files to process.."}

Related

Cleaning up filenames from MAC using Powershell

I'm writing a script that iterates over files that are copied from a MAC computer to a Exfat disk and checks the name of the files for Windows forbidden characters.(Writing it in PowerShell)
And hopefully replace the forbidden characters with another character, for example a "-".
Why i am doing this is because i see it as a good way for me to practice coding and it might be used in my work when we get users with a lot of local files that we want to move to Onedrive.(Onedrive has a function to rename but it doesn't touch the forbidden characters, and i don't know Bash)
The issue is when I'm trying to find the characters within the script itself, it cant find the characters if i write them in the script.(For example if i write that it should look for ">")
Even if i escape the characters it just skips it(Or rather doesn't find it).
It just skips over the file i know has one in it, at first i though it might be due to encoding, but no matter what i use as a default encoding it wont display the filename correctly.(I assume this is due to how Windows reads filenames?)
edit: These are the forbidden characters im goint to look for " * : < > ? / \ |
The script itself is able to remove letters and stuff if i ask it to.
I also tried getting the char of the byte([byte][char]"") but i get this error:
Cannot convert value "" to type "System.Byte". Error: "Value was either too large or too small for an unsigned byte." Edit: the  changed by itself during the day not sure what to say.
If i just add it to the function it just returns the error:Rename-Item : The input to the script block for parameter 'NewName' failed. Exception calling "Replace" with "2" argument(s): "String cannot be of zero length.
The characters are displayed like this in visual studio code.
Any ideas are welcome or if you know of any better ways of doing it?(Maybe its better if i just learn bash. )
Here is the script itself:
edit: cleaned up the script abit and some small changes.
$provided_path = Read-Host "What Directory and its subfolders do you want to check?"
# Iterates over the folders and files within.
Write-Host "Creating list of files..."
$dictionary_filenames = ""
$dictionary_filenames = Get-ChildItem -Path $provided_path -Recurse -Force -File | Select-Object FullName,BaseName,Extension
# Resetting counter
$counter_skipped = 0
# Function for character replacment
function rename_file_name($names_function,$forbidden_char){
$old_name = $names_function.BaseName
$new_name = $names_function | Rename-Item -LiteralPath $names_function.FullName -NewName{$_.BaseName.Replace("$forbidden_char","-") + $_.extension} -PassThru
if($old_name -ne $new_name.BaseName){
Write-host "$old_name changed to $new_name"
}
}
foreach($names in $dictionary_filenames){
if($names.BaseName[0] -eq "." -and $names.BaseName[1] -match "_"){
$counter_skipped ++
$counter ++
continue
}
else{
if($names.BaseName[0] -eq " " -or $names.BaseName[-1] -eq " "){
$old_name = $names.BaseName
$new_name = $names | Rename-Item -LiteralPath $names.FullName -NewName{$_.BaseName.trim() + $_.extension} -PassThru
Write-Host "Trimming whitespace: $old_name"
}
else{
Write-Host "Trimming not needed "$names.BaseName
}
Write-host "Checking forbidden characters "$names.BaseName
rename_file_name $names ">"
rename_file_name $names "<"
rename_file_name $names "/"
}
}
Write-Host "Files checked: "$dictionary_filenames.Count
Write-Host "Files Skipped: "$counter_skipped
Read-Host 'Close window by pressing "Enter"'```
 is U+F021, two bytes long or [int16]. You can put it in a utf8 with bom encoded script.

Incrementing variables in powershell

I'm new to PowerShell and am trying to create a script that goes through a csv file (simple name,value csv) and loads each new line in it as a variable and then runs a function against that set of variables.
I've had success at getting it to work for 1 variable by using the following code snippet:
Import-Csv -Path C:\something\mylist.csv | ForEach-Object {
New-Variable -Name $_.Name -Value $_.Value -Force
}
My csv looks like this:
name,value
RegKey1,"Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\LanmanWorkstation"
Basically it's a list of registry keys each named as RegKey# and then the path of that reg key is the intended value of the variable.
I'm currently playing around with the "Test-Path" cmdlet that just prints out true/false if the passed reg-key exists and then just prints out some text based on if it found the reg key or not.
That snippet looks like so:
Test-Path $RegKey1
IF ($LASTEXITCODE=0) {
Write-Output "It worked"
}
else {
Write-Output "It didn't work"
}
This works fine however what I'm trying to achieve is for powershell to run this cmdlet against each of the lines in the csv file - basically checking each reg key in it and then doing whatever specified to it.
What I'm trying to avoid is declaring hundreds of variables for every regkey I plan on using but instead have this one function that just runs through the csv and every time it runs, it increments the number next to the variable's name - RegKey1,RegKey2,RegKey3 etc.
Let me know if there's a way to do this in powershell or a better way of approaching this altogether. I also apologize in advance if I've not provided enough info, please do let me know.
You need to place your if statement in the Foreach-Object loop. This will also only work, if your variable all get the same name of $RegKey. To incriment, you may use the for loop.
Import-Csv -Path C:\something\mylist.csv | ForEach-Object {
New-Variable -Name $_.Name -Value $_.Value -Force
IF (Test-Path $RegKey1) {
Write-Output "It worked"
}
else {
Write-Output "It didn't work"
}
}
The if statement returns a boolean value of $true, or $false. So theres no need to use $LastExitCode by placing the Test-Path as the condition to evaluate for.
Alternatively, you can use the Foreach loop to accomplish the same thing here:
$CSV = Import-Csv -Path C:\something\mylist.csv
Foreach($Key in $CSV.Value){
$PathTest = Test-Path -Path $Key
if($PathTest) {
Write-Output "It worked"
} else {
Write-Output "It didn't work"
}
}
By iterating(reading through the list 1 at a time) through the csv only selecting the value(Reg Path), we can test against that value by assigning its value to the $PathTest Variable, to be evaluated in your if statement just like above; theres also no need to assign it to a variable and we can just use the Test-Path in your if statement like we did above as well for the same results.

PowerShell to filter file size

I am trying to write a script using PowerShell to get file size 0kb as mentioned below
$FileExists1 = 'C:\Users\iskandar\Desktop\TEST\*\test0700.txt'
IF (Test-Path $FileExists1) {
If ((Get-Item $FileExists1).length -gt 0kb) {
Write-Output "All file size is good!"
}
Else {
Write-Output " There is a file with 0KB, Please inform support staff"
}
}
if there is multiple folder with multiple file, the script not filter the 0KB file.
for example : lets say I have 30 files and only one file with 0KB, when I run those script, it shows "All file size is good!".
Can anyone advice?. Thank you
try this:
$files=gci "C:\Users\iskandar\Desktop\TEST" -file -Recurse | where Length -le 0Kb | select -First 1
if ($files.Count -gt 0)
{
"There is a file with 0KB, Please inform support staff"
}
else
{
"All file size is good!"
}
Though Esperento57 has provided a working solution, let's see what is wrong in the original code.
The problem happens as you are hit by object mismatch. Multiple objects have same attributes that contain different things.
For a single file, Get-Item will return a FileInfo object that contains file's size in its .Length attribute.
For multiple files, Get-Item will return an array of FileInfo objects. Its .Length attribute contains the length of the array itself. Thus the statement
If ((Get-Item $FileExists1).length -gt 0kb) {
actually is processed as pseudocode
if ($FileExists1-the-array contains more than 0 elements) {

Where Command not Working? [duplicate]

Very new to coding in general, so I fear I am missing something completely obvious. I want my program to check for a file. If it is there, just continue the code. If it has not arrived, continue cheking for a given amount of time, or untill the file shows up. My loop works on its own, so when i only select the do-part in Powershell ISE, it works. But when i try running it inside the if statement, nothing happens. The loops doesnt begin.
$exists= Test-Path $resultFile
$a = 1
if ($exists -eq "False")
{
do
{
$a++
log "Now `$a is $a "
start-sleep -s ($a)
$exists= Test-Path $resultFile
write-host "exists = $exists"
}
while (($a -le 5) -and ($exists -ne "True"))
}
Another way of doing this is using a while loop:
$VerbosePreference = 'Continue'
$file = 'S:\myFile.txt'
$maxRetries = 5; $retryCount = 0; $completed = $false
while (-not $completed) {
if (Test-Path -LiteralPath $file) {
Write-Verbose "File '$file' found"
$completed = $true
# Do actions with your file here
}
else {
if ($retryCount -ge $maxRetries) {
throw "Failed finding the file within '$maxRetries' retries"
} else {
Write-Verbose "File not found, retrying in 5 seconds."
Start-Sleep '5'
$retryCount++
}
}
}
Some tips:
Try to avoid Write-Host as it kills puppies and the pipeline (Don Jones). Better would be, if it's meant for viewing the script's progress, to use Write-Verbose.
Try to be consistent in spacing. The longer and more complex your scripts become, the more difficult it will be to read and understand them. Especially when others need to help you. For this reason, proper spacing helps all of us.
Try to use Tab completion in the PowerShell ISE. When you type start and press the TAB-key, it will automatically propose the options available. When you select what you want with the arrow down/up and press enter, it will nicely format the CmdLet to Start-Sleep.
The most important tip of all: keep exploring! The more you try and play with PowerShell, the better you'll get at it.
As pointed out in comments, your problem is that you're comparing a boolean value with the string "False":
$exists -eq "False"
In PowerShell, comparison operators evaluate arguments from left-to-right, and the type of the left-hand argument determines the type of comparison being made.
Since the left-hand argument ($exists) has the type [bool] (a boolean value, it can be $true or $false), PowerShell tries to convert the right-hand argument to a [bool] as well.
PowerShell interprets any non-empty string as $true, so the statement:
$exists -eq "False"
is equivalent to
$exists -eq $true
Which is probably not what you intended.

Powershell loop only if condition is true

Very new to coding in general, so I fear I am missing something completely obvious. I want my program to check for a file. If it is there, just continue the code. If it has not arrived, continue cheking for a given amount of time, or untill the file shows up. My loop works on its own, so when i only select the do-part in Powershell ISE, it works. But when i try running it inside the if statement, nothing happens. The loops doesnt begin.
$exists= Test-Path $resultFile
$a = 1
if ($exists -eq "False")
{
do
{
$a++
log "Now `$a is $a "
start-sleep -s ($a)
$exists= Test-Path $resultFile
write-host "exists = $exists"
}
while (($a -le 5) -and ($exists -ne "True"))
}
Another way of doing this is using a while loop:
$VerbosePreference = 'Continue'
$file = 'S:\myFile.txt'
$maxRetries = 5; $retryCount = 0; $completed = $false
while (-not $completed) {
if (Test-Path -LiteralPath $file) {
Write-Verbose "File '$file' found"
$completed = $true
# Do actions with your file here
}
else {
if ($retryCount -ge $maxRetries) {
throw "Failed finding the file within '$maxRetries' retries"
} else {
Write-Verbose "File not found, retrying in 5 seconds."
Start-Sleep '5'
$retryCount++
}
}
}
Some tips:
Try to avoid Write-Host as it kills puppies and the pipeline (Don Jones). Better would be, if it's meant for viewing the script's progress, to use Write-Verbose.
Try to be consistent in spacing. The longer and more complex your scripts become, the more difficult it will be to read and understand them. Especially when others need to help you. For this reason, proper spacing helps all of us.
Try to use Tab completion in the PowerShell ISE. When you type start and press the TAB-key, it will automatically propose the options available. When you select what you want with the arrow down/up and press enter, it will nicely format the CmdLet to Start-Sleep.
The most important tip of all: keep exploring! The more you try and play with PowerShell, the better you'll get at it.
As pointed out in comments, your problem is that you're comparing a boolean value with the string "False":
$exists -eq "False"
In PowerShell, comparison operators evaluate arguments from left-to-right, and the type of the left-hand argument determines the type of comparison being made.
Since the left-hand argument ($exists) has the type [bool] (a boolean value, it can be $true or $false), PowerShell tries to convert the right-hand argument to a [bool] as well.
PowerShell interprets any non-empty string as $true, so the statement:
$exists -eq "False"
is equivalent to
$exists -eq $true
Which is probably not what you intended.