PowerShell Wildcard Not Returning All Files - powershell

I'm new to PowerShell and been trying to get this script to work.
If ((Get-Date -UFormat %a) -eq "Mon") {$intSubtract = -3}
Else {$intSubtract = -1}
$datDate = (Get-Date).AddDays($intSubtract)
Write-Output "Find expected file --------------"
$strDate = ($datDate).ToString('yyyyMMdd')
Write-Host "strDate: $strDate"
$arrGetFile = Get-ChildItem -Path "\\Computer\Data\States\NorthDakota\Cities\*_Bismark_$strDate*.txt"
$strLocalFileName = $arrGetFile
If ($arrGetFile.count -ne 2)
{
Throw "No file or more than two files with today's date exists!"
}
Else {$strLocalFileName = $arrGetFile[0].Name}
Write-Output "Found file $strLocalFileName --------------"
#Encrypt each file
foreach ($arrGetFile in $strPath)
{
Write-Output "Start Encrypt --------------"
$strPath = "\\Computer\Data\States\NorthDakota\Cities\"
$FileAndPath = Join-Path $strPath $strLocalFileName
$Recipient = "0xA49B4B5D"
Import-Module \\JAMS\C$\PSM_PGP.psm1
Get-Module Encrypt
Encrypt $FileAndPath $Recipient
$strLocalFileNamePGP = $strLocalFileName + ".pgp"
Write-Output "End Encrypt --------------"
}
#Archive files
Write-Output "Archiving --------------"
move-item -path \\Computer\Data\States\NorthDakota\Cities\*_Bismark_$strDate*.txt -destination \\Computer\Data\States\NorthDakota\Cities\Archive
The Cities folder will contain two files. Example 2015_Bismark_20150626_183121.txt and 2015_Bismark_20150626_183121_Control.txt
I am trying to get both files encrypted however it is only finding and encrypting the file without _Control. It is archiving both files correctly.
Not sure what I am missing to also find the control file.

Your for loop is incorrect. You have foreach ($arrGetFile in $strPath), but $strPath doesn't seem to contain anything at that point.
Your for loop should be:
foreach ($LocalFile in $arrGetFile)
And you need to remove the following line:
$strLocalFileName = $arrGetFile
This is making $strLocalFileName an array of file objects, but later in the script you are treating it like a string. You may have more logical errors--you need to walk through the script very carefully and identify each variable and make sure it contains what you expect it to contain.
In general you seem to be treating arrays of non-string objects as if they are strings. Note that I changed your $strLocalFileName variable to $LocalFile. This is because it is a file object, not a string object.
Following is a sample that just shows that the for loop iterates through the both files.
If ((Get-Date -UFormat %a) -eq "Mon") {$intSubtract = -3}
Else {$intSubtract = -1}
$datDate = (Get-Date).AddDays($intSubtract)
Write-Output "Find expected file --------------"
$strDate = ($datDate).ToString('yyyyMMdd')
Write-Host "strDate: $strDate"
$arrGetFile = Get-ChildItem -Path "\\Computer\Data\States\NorthDakota\Cities\*_Bismark_$strDate*.txt"
If ($arrGetFile.count -ne 2)
{
Throw "No file or more than two files with today's date exists!"
}
Write-Output "Found files " ($arrGetFile | select Name | fl) "--------------"
#Process each file
foreach ($LocalFile in $arrGetFile)
{
$FileAndPath = Join-Path $LocalFile.DirectoryName $LocalFile
$FileAndPath
}
Start with this and then carefully add your encryption processing back into the loop.
Also, The line that assigns $FileAndPath could be removed. You can just use $LocalFile.FullName wherever you need the full path and filename.

Related

Check if folder exists based on a partial string, create new folder if it doesn't, change name if it does

Short version: I'm trying to get a looping if/else statement to work. What I'm trying to get it to do is check to see if a folder exists that contains a particular string ending in a three-digit number (the variable $FolderSeqSRC below); if it doesn't, I want to create a folder with that string as its name. If it does, I want it to increment up the three-digit number and then go through the process again. This is the code that I have:
$FolderDate = (Get-Date).ToString('yyMMdd');
$FolderSeqSRC = 1;
$FolderSeq = ([string]$FolderSeqSRC).PadLeft(3,'0');
$FolderDescript = "Test"
$NewFolderName = "$FolderDate-$FolderSeq $FolderDescript";
$FolderSearchName = "$FolderDate-$FolderSeq"
$OldFileName = "C0";
$NewFileName = "$FolderDate-$FolderSeq-";
Write-Host "$FolderDate";
Write-Host "$NewFolderName";
while (-not $completed) {
if (-Not (Test-Path -Path $targetDir\$FolderSearchName*)) {
"Path $FolderSearchName doesn't exist: creation in progress."
$completed = $true
} else {
"Path $FolderSearchName exists!"
$FolderSeqSRC++;
$FolderSeq = ([string]$FolderSeqSRC).PadLeft(3,'0');
$FolderSearchName = "$FolderDate-$FolderSeq"
$NewFolderName = "$FolderDate-$FolderSeq $FolderDescript";
$NewFileName = "$FolderDate-$FolderSeq-";
"Trying path $FolderSearchName next."
$completed = $false
}
New-Item -ItemType Directory -Force -Path "$targetDir\$NewFolderName"
$completed = $true
}
I'm halfway home. It checks successfully to see if a folder exists with a -001 in it, and if it doesn't, it creates it exactly the way I want. If the 001 folder does exist, it creates a -002 folder. The problem is it won't increment past -002. I thought I had it set up properly to loop, but apparently I'm missing something. An earlier attempt had it stuck in an endless loop that DID increment properly, so I know this is close.
(This is part of a larger script that retrieves files off a camera SD card so some of these variables may look extraneous but aren't.)
Okay so turns out as usual I was overthinking things. This is what finally made it happen:
$FolderDate = (Get-Date).ToString('yyMMdd');
$FolderSeqSRC = 1;
$FolderSeq = ([string]$FolderSeqSRC).PadLeft(3,'0');
$NewFolderName = "$FolderDate-$FolderSeq $FolderDescript";
$FolderSearchName = "$FolderDate-"
Write-Host "$FolderDate";
Write-Host "$NewFolderName";
$CheckPath = #(Get-ChildItem $targetDir -Recurse | Where-Object { $_.PSIsContainer -and $_.Name.StartsWith($FolderSearchName)}).Count;
Write-Host "Number of Existing Items: $CheckPath";
$FolderSeqSRC2 = $FolderSeqSRC + $CheckPath;
$FolderSeq = ([string]$FolderSeqSRC2).PadLeft(3,'0');
Write-Host "Increment should be: $FolderSeq"
PAUSE
$FolderSearchName = "$FolderDate-$FolderSeq"
$NewFolderName = "$FolderDate-$FolderSeq $FolderDescript";
$NewFileName = "$FolderDate-$FolderSeq-";
New-Item -ItemType Directory -Force -Path "$targetDir\$NewFolderName"
The answer was to simply not rely on an if/else loop--instead I found a way to tell Get-ChildItem to tell me how many folder names matched the partial string of the just the date, and then add that number to 1. The idea being that if it doesn't find any, then it adds 0, and the folder it creates is -001. If it finds two existing folders, it adds 2+1, to get me the new folder name 230106-003.

Trouble linking commands together

So i'm pretty new to powershell and I'm trying to list all contents of a directory(on my vm) while stating if each is a reg file or directory along with it's path/size.
the code I have is:
#!/bin/bash
cd c:\
foreach ($item in get-childitem -Path c:\) {
Write-Host $item
}
########
if(Test-Path $item){
Write-Host "Regular File" $item
}
else {
Write-Host "Directory" $item
}
I can get all of the contents to print, but when I try to state whether file/directory, only one .txt file says "Regular File" next to it. I've been at it for hours on end and get figure it out. Also, my output doesn't state "directory" next to directories...
Here is an example of how you can enumerate the files and folders on your C Drive one level deep with their current size (if it's a folder, look for the files inside and get a sum of it's Length). Regarding trying to "state whether file / directory", you don't need to apply any logic to it, FileInfo and DirectoryInfo have an Attributes property which gives you this information already.
Get-ChildItem -Path C:\ | & {
process {
$object = [ordered]#{
Attributes = $_.Attributes
Path = $_.Name # change to $_.FullName for the Path
Length = $_.Length / 1mb
}
if($_ -is [IO.DirectoryInfo]) {
foreach($file in $_.EnumerateFiles()) {
$object['Length'] += $file.Length / 1mb
}
}
$object['Length'] = [math]::Round($object['Length'], 2).ToString() + ' Mb'
[pscustomobject] $object
}
}
If you want something more complex, i.e. seeing the hierarchy of a directory, like tree does, with the corresponding sizes you can check out this module.

Powershell: Logging foreach changes

I have put together a script inspired from a number of sources. The purpose of the powershell script is to scan a directory for files (.SQL), copy all of it to a new directory (retain the original), and scan each file against a list file (CSV format - containing 2 columns: OldValue,NewValue), and replace any strings that matches. What works: moving, modifying, log creation.
What doesn't work:
Recording in the .log for the changes made by the script.
Sample usage: .\ConvertSQL.ps1 -List .\EVar.csv -Files \SQLFiles\Rel_1
Param (
[String]$List = "*.csv",
[String]$Files = "*.sql"
)
function Get-TimeStamp {
return "[{0:dd/MM/yyyy} {0:HH:mm:ss}]" -f (Get-Date)
}
$CustomFiles = "$Files\CUSTOMISED"
IF (-Not (Test-Path $CustomFiles))
{
MD -Path $CustomFiles
}
Copy-Item "$Files\*.sql" -Recurse -Destination "$CustomFiles"
$ReplacementList = Import-Csv $List;
Get-ChildItem $CustomFiles |
ForEach-Object {
$LogFile = "$CustomFiles\$_.$(Get-Date -Format dd_MM_yyyy).log"
Write-Output "$_ has been modified on $(Get-TimeStamp)." | Out-File "$LogFile"
$Content = Get-Content -Path $_.FullName;
foreach ($ReplacementItem in $ReplacementList)
{
$Content = $Content.Replace($ReplacementItem.OldValue, $ReplacementItem.NewValue)
}
Set-Content -Path $_.FullName -Value $Content
}
Thank you very much.
Edit: I've cleaned up a bit and removed my test logging files.
Here's the snippet of code that I've been testing with little success. I put the following right under $Content= Content.Replace($ReplacementItem.OldValue, $ReplacementItem.NewValue)
if ( $_.FullName -like '*TEST*' ) {
"This is a test." | Add-Content $LogFile
}
I've also tried to pipe out the Set-Content using Out-File. The outputs I end up with are either a full copy of the contents of my CSV file or the SQL file itself. I'll continue reading up on different methods. I simply want to, out of hundreds to a thousand or so lines, to be able to identify what variables in the SQL has been changed.
Instead of piping output to Add-Content, pipe the log output to: Out-File -Append
Edit: compare the content using the Compare-Object cmdlet and evaluate it's ouput to identify where the content in each string object differs.

Renaming folders from a list

I have a text file list of 56 folders that includes the full paths to a set of folders. I need to rename the folder at the end of the path.
Example:
Original: \this folder\needs to\move
New: \this folder\needs to\move.moved
I am totally new at powershell and trying to learn. I thought this might be a good way to start. Any help would be greatly appreciated.
# Get the content of the list
# in this case, a text file with no heading, and one path per line
$listContent = Get-Content $ENV:USERPROFILE\Desktop\list.txt
# Loop over each child folder and rename it
foreach($line in $listContent)
{
# check if the current path is valid
$pathTest = Test-Path -Path $line
if($pathTest -eq $True)
{
Write-Output "`nOld path: $($line)"
$newName = $line + ".moved"
Write-Output "New name: $newName"
try
{
# on success, write out message
Rename-Item -Path $line -NewName $newName -Force
# split the string from the file and get the data after the last \ for readability
Write-Output "`nSuccessfully changed directory name $($line.split('\')[-1]) to $newName"
}
catch
{
# on error, throw first error in the Error array
throw $Error[0]
}
}
else {
Write-Output "$($line) is not a valid path"
}
}
Write-Output "`nEnd of script!"

Powershell output formatting?

I have a script that scans for a specific folder in users AppData folder. If it finds the folder, it then returns the path to a txt file. So we can see the computer name and username where it was found.
I would like to be able to format the what is actually written to the text file, so it removes everything from the path except the Computer and User names.
Script:
foreach($computer in $computers){
$BetterNet = "\\$computer\c$\users\*\AppData\Local\Google\Chrome\User Data\Default\Extensions\gjknjjomckknofjidppipffbpoekiipm"
Get-ChildItem $BetterNet | ForEach-Object {
$count++
$betternetCount++
write-host BetterNet found on: $computer
Add-Content "\\SERVERNAME\PowershellScans\$date\$time\BetterNet.txt" $_`n
write-host
}
}
The text files contain information like this
\\computer-11-1004S10\c$\users\turtle\AppData\Local\Google\Chrome\User Data\Default\Extensions\gjknjjomckknofjidppipffbpoekiipm
\\computer-1004-24S\c$\users\camel\AppData\Local\Google\Chrome\User Data\Default\Extensions\gjknjjomckknofjidppipffbpoekiipm
\\computer-1004-23S\c$\users\rabbit\AppData\Local\Google\Chrome\User Data\Default\Extensions\gjknjjomckknofjidppipffbpoekiipm
If you have each line in a form of the string $string_containing_path then it is easy to split using split method and then add index(1) and (4) that you need:
$afterSplit = $string_containing_path.Split('\')
$stringThatYouNeed = $afterSplit[1] + " " + $afterSplit[4]
You can also use simple script that will fix your current logs:
$path_in = "C:\temp\list.txt"
$path_out= "C:\temp\output.txt"
$reader = [System.IO.File]::OpenText($path_in)
try {
while($true){
$line = $reader.ReadLine()
if ($line -eq $null) { break }
$line_after_split_method = $line.Split('\')
$stringToOutput = $line_after_split_method[1] + " " + $line_after_split_method[4] + "`r`n"
add-content $path_out $stringToOutput
}
add-content $path_out "End"
}
finally {
$reader.Close()
}
If you split your loop into two foreach loops, one for computer and user directory it would be easier to output the name of the user directory.
$output = foreach($computer in $computers){
$UserDirectories = Get-ChildItem "\\$computer\c$\users\" -Directory
foreach ($Directory in $UserDirectories) {
$BetterNet = Get-ChildItem (Join-Path $Directory.fullname "\AppData\Local\Google\Chrome\User Data\Default\Extensions\gjknjjomckknofjidppipffbpoekiipm")
Add-Content "\\SERVERNAME\PowershellScans\$date\$time\BetterNet.txt" "$computer $($Directory.name)`r`n"
write-host BetterNet found on: $computer
$BetterNet
}
}
$output.count