I am having a text file that has content in this manner.
One;Thomas;Newyork;2020-12-31 14:00:00;0
Two;David;London;2021-01-31 12:00:00;0
Three;James;Chicago;2021-01-20 15:00:00;0
Four;Edward;India;2020-12-25 15:00:00;0
In these entries according to date time, two are past entries and two are future entries. The last 0 in the string indicates the Flag. With the past entries that flag needs to be changed to 1.
Consider all the entries are separated with the array. I tried this block of code but its not working to solve the problem here.
for ($item=0 ; $item -lt $entries.count ; $item++)
{
if ($entries.DateTime[$item] -lt (Get-Date -Format "yyyy-MM-dd HH:mm:ss"))
{
$cont = Get-Content $entries -ErrorAction Stop
$string = $entries.number[$item] + ";" + $entries.name[$item] + ";" +
$entries.city[$item]+ ";" + $entries.DateTime[$item]
$lineNum = $cont | Select-String $string
$line = $lineNum.LineNumber + 1
$cont[$line] = $string + ";1"
Set-Content -path $entries
}
}
I am getting errors with this concept.
Output should come as:-
One;Thomas;Newyork;2020-12-31 14:00:00;1 ((Past Deployment with respect to current date)
Two;David;London;2021-01-31 12:00:00;0
Three;James;Chicago;2021-01-20 15:00:00;0
Four;Edward;India;2020-12-25 15:00:00;1 (Past Deployment with respect to current date)
This output needs to be overwritten on the file from where the content is extracted ie Entries.txt
param(
$exampleFileName = "d:\tmp\file.txt"
)
#"
One;Thomas;Newyork;2020-12-31 14:00:00;0
Two;David;London;2021-01-31 12:00:00;0
Three;James;Chicago;2021-01-20 15:00:00;0
Four;Edward;India;2020-12-25 15:00:00;0
"# | Out-File $exampleFileName
Remove-Variable out -ErrorAction SilentlyContinue
Get-Content $exampleFileName | ForEach-Object {
$out += ($_ -and [datetime]::Parse(($_ -split ";")[3]) -gt [datetime]::Now) ? $_.SubString(0,$_.Length-1) + "1`r`n" : $_ + "`r`n"
}
Out-File -InputObject $out -FilePath $exampleFileName
Script
$ADUser = Get-ADUser
if($ADUser -ne "") {echo "there are existing ADUsers!"} #
$Zeilen = (Get-Content C:\Users\Administrator\Documents\users.csv | Measure-Object –Line).Lines #import file, count lines with Measure-Object(mo)(-> output object), ".Lines" takes just number from Measure-Object and convert it to a number
$Zeilen -= 1 # "-1" because 1. line = header without relevant information
$Ausgabe = Import-Csv C:\Users\Administrator\Documents\users.csv
$password = "Ausbildung2020" | ConvertTo-SecureString -AsPlainText -Force #is disabled without password
###################
#creates list with existing users
$Userlist = ""
$CsvData = (Get-ADUser).DistinguishedName | Select-Object -Skip 3 #removes first 3 Zeilen, which contains Admin, Guest und kgrtgt because the are irrelevant
$ZeilenCsvData = $CsvData.count #line amount from (Get-ADUser).DistinguishedName
for($line = 0;$line -lt $ZeilenCsvData; $line++ ) #-lt oder -le ?
{
$UserLine = $CsvData[$line]
$user1 = $UserLine.Split(",")
$user2 = $user1[0].Split("=")
$user3 = $user2[1] #extract Username from String
$UserList += $user3 + "`r`n" #paste Username from current Iteration to $UserList
}
###################
#check if ADUser exists
for ($loop = 0; $loop -lt $Zeilen; $loop++) #-lt oder -le ? #execute loop as often as lines in (Csv-file with (new) Users) exists
{
for($i = 0; $i -lt $ZeilenCsvData ; $i++) #$ZeilenCsvData: number of lines from Get-ADUser without Admin, Guest und kgrtgt
{
if($Ausgabe[$loop].Name -eq $UserList.[$i]) #!!line with problem!!
{
$match = $true
break
}
}
if($match -eq $true){ continue } #ends Iteration and continue with new one if User exists
###################
#create User if it doesn't exist
New-ADUser -Name $Ausgabe[$loop].Name `
-GivenName $Ausgabe[$loop].GivenName `
-Surname $Ausgabe[$loop].Surname `
-City $Ausgabe[$loop].City `
-AccountPassword $password `
-path "OU=Benutzer,DC=dmamgt,DC=local" `
Enable-ADAccount -Identity $Ausgabe[$loop].Name #requirement: password matches standard
}
Problem
In the problem line the „ [$ “ marked red and I get those errors which make the script unexecutable
Task
I got the task to create a organizational unit called "Benutzer" in which I should create 20 Users with some properties like name, city,password, enabled,... which I imported from a csv file. But I have to check whether the user already exists if so the loop should go to the next user to create it.
Errors:
At C:\Users\Administrator\Documents\extended New-ADUser mit csv.ps1:36 char:48
+ if($Ausgabe[$loop].Name -eq $UserList.[$i])
+ ~
Missing type name after '['.
At C:\Users\Administrator\Documents\extended New-ADUser mit csv.ps1:36 char:47
+ if($Ausgabe[$loop].Name -eq $UserList.[$i])
+ ~
Missing property name after reference operator.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : MissingTypename
Method invocation failed because [System.Char] does not contain a method named 'Split'.
At C:\Users\Administrator\Documents\extended New-ADUser mit csv.ps1:23 char:5
+ $user1 = $UserLine.Split(",")
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
Make $UserList an array:
$UserList = #()
Add items like this:
$UserList += $user
And this is how you index an array (without the dot)
$UserList[$i]
There might be some other issues with your script too, I didn't read it fully, but I hope this will get you started.
Background: I've been using Netwrix to audit permissions to network shares for a few years now and It's only ever worked smoothly 1 time..... So I've decided to move on to just an automated powershell script. I've run into a block. When I try to parse out the group members, it doesn't like the network name in front of the group name (TBANK). Then I also need to take the next step of just showing the name instead of the whole output of get-adgroupmember. Any help would be greatly appreciated as I'm very to to scripting with powershell. Current script below:
$OutFile = "C:\users\user1\Desktop\test.csv" # Insert folder path where you want to save your file and its name
$Header = "Folder Path,IdentityReference, Members,AccessControlType,IsInherited,InheritanceFlags,PropagationFlags"
$FileExist = Test-Path $OutFile
If ($FileExist -eq $True) {Del $OutFile}
Add-Content -Value $Header -Path $OutFile
$Folder = "\\server1.tbank.com\share1"
$ACLs = get-acl $Folder | ForEach-Object { $_.Access }
Foreach ($ACL in $ACLs){
$ID = $ACL.IdentityReference
$ID = $ID -replace 'TBANK\' , ''
$ACType = $ACL.AccessControlType
$ACInher = $ACL.IsInherited
$ACInherFlags = $ACL.InheritanceFlags
$ACProp = $ACL.PropagationFlags
$Members = get-adgroupmember $ID.
$OutInfo = $Folder + "," + $ID + "," + $Members + "," + $ACType + "," + $ACInher + "," + $ACInherFlags + "," + $ACProp
Add-Content -Value $OutInfo -Path $OutFile
}
First of all, there is a way better way to output a CSV file than by trying to write each row yourself (with the risk of missing out required quotes), called Export-Csv.
To use that cmdlet, you wil need to create an array of objects which is not hard to do.
$OutFile = "C:\users\user1\Desktop\test.csv" # Insert folder path where you want to save your file and its name
$Folder = "\\server1.tbank.com\share1"
# get the Acl.Access for the folder, loop through and collect PSObjects in variable $result
$result = (Get-Acl -Path $Folder).Access | ForEach-Object {
# -replace uses regex, so you need to anchor to the beginning of
# the string with '^' and escape the backslash by doubling it
$id = $_.IdentityReference -replace '^TBANK\\' # remove the starting string "TBANK\"
# Get-ADGroupMember can return users, groups, and computers. If you only want users, do this:
# $members = (Get-ADGroupMember -Identity $id | Where-Object { $_.objectClass -eq 'user'}).name -join ', '
$members = (Get-ADGroupMember -Identity $id).name -join ', '
# output an onbject with all properties you need
[PsCustomObject]#{
'Folder Path' = $Folder
'IdentityReference' = $id
'Members' = $members
'AccessControlType' = $_.AccessControlType
'IsInherited' = $_.IsInherited
'InheritanceFlags' = $_.InheritanceFlags -join ', '
'PropagationFlags' = $_.PropagationFlags -join ', '
}
}
# output on screen
$result | Format-List
# output to CSV file
$result | Export-Csv -Path $OutFile -Force -UseCulture -NoTypeInformation
I've added a lot of inline comments to hopefully make things clear for you.
The -UseCulture switch in the Export-Csv line makes sure the field delimiter that is used matches what is set in your system as list separator. This helps when opening the csv file in Excel.
P.S> the Get-ADGroupMember cmdlet also has a switch called -Recursive. With that, it will also get the members from groups inside groups
I would like to delete all VERTICAL and SMALL pictures from a certain folder.
I have a folder that I do not want the vertical pictures or pictures with dimensions less than 600 x 600 pixels. I believe that PowerShell is the best thing to use since I cannot get Python to work on my computer.
I am doing this because I do not want to manually delete the vertical/small pictures from my folder each day. (It gets new ones every day)
Any help would be greatly appreciated!!
Here is my code :
cd C:\Users\Jack\Desktop\Test
$c = 5
Function Get-FileMetaData {
Param([string[]]$folder)
foreach($sFolder in $folder) {
$a = 0
$b = 1
$objShell = New-Object -ComObject Shell.Application
$objFolder = $objShell.namespace($sFolder)
foreach ($File in $objFolder.items()) {
$FileMetaData = New-Object PSOBJECT
for ($a ; $a -le 266; $a++) {
if($objFolder.getDetailsOf($File, $a)) {
$hash += #{$($objFolder.getDetailsOf($objFolder.items, $a)) =
$($objFolder.getDetailsOf($File, $a)) }
$FileMetaData | Add-Member $hash
if ($($objFolder.getDetailsOf($objFolder.items, $a)) -eq "Height") {
Write-Host $($objFolder.getDetailsOf($objFolder.items, $a)) =====
$($objFolder.getDetailsOf($File, $a))
}
if ($($objFolder.getDetailsOf($objFolder.items, $a)) -eq "Width") {
Write-Host $($objFolder.getDetailsOf($objFolder.items, $a)) =====
$($objFolder.getDetailsOf($File, $a))
}
if ($($objFolder.getDetailsOf($objFolder.items, $a)) -eq "Name") {
Write-Host $($objFolder.getDetailsOf($objFolder.items, $a)) =====
$($objFolder.getDetailsOf($File, $a))
}
$b++
$hash.clear()
} #end if
} #end for
Write-Host $a
$a=0
$FileMetaData
} #end foreach $file
$c++
Write-Host c = $c
} #end foreach $sfolder
} #end Get-FileMetaData
Write-Host c = $c
$h = Get-FileMetaData C:\Users\Jack\Desktop\Test | select Height
$w = Get-FileMetaData C:\Users\Jack\Desktop\Test | select Width
$n = Get-FileMetaData C:\Users\Jack\Desktop\Test | select Name
$h
Write-Host w = $w
Write-Host name = $n
$SpecChars = '!', "{", "}", '"', '£', '$', '%', '&', '^', '*', '(', ')', '#', '=', '+', '¬', '`', '\', '<', '>', '?', '/', ':', ';', '#', '~', "'", '-', "Name", "N", "a", "m", "e", ' '
$remspecchars = [string]::join('|', ($SpecChars | % {[regex]::escape($_)}))
if (($h) -replace '\D+(\d+)','$1' -gt ($w) -replace '\D+(\d+)','$1') {
Write-Host "VERTICAL"
Write-Host name = $n
$d = $n -replace $remspecchars, ""
$d.split()
Write-Host $d
$tally = 0
while($tally -ne $d.Count) {
del $d[$tally]
$tally++
}
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
}
Write-Host "Finished"
try this
$folder = 'C:\temp\Pictures\'
$image = New-Object -ComObject Wia.ImageFile
$pictures = Get-ChildItem $folder *.jpg | ForEach-Object {
$image.LoadFile($_.fullname)
$size = $image.Width.ToString() + 'x' + $image.Height.ToString()
$orientation = $image.Properties | ? {$_.name -eq 'Orientation'} | % {$_.value}
if ($orientation -eq 6) {
$rotated = $true
} else {
$rotated = $false
}
$heightGtWidth = if ([int]$image.Height.ToString() -gt [int]$image.Width.ToString()) {
$true
} else {
$false
}
[pscustomobject]#{
Fullname = $_.FullName
Size = $size
Rotated = $rotated
HeightGtWidth = $heightGtWidth
}
}
$pictures
I'm trying to format large text files (~300MB) between 0 to 3 columns :
12345|123 Main St, New York|91110
23456|234 Main St, New York
34567|345 Main St, New York|91110
And the output should be:
000000000012345,"123 Main St, New York",91110,,,,,,,,,,,,
000000000023456,"234 Main St, New York",,,,,,,,,,,,,
000000000034567,"345 Main St, New York",91110,,,,,,,,,,,,
I'm new to powershell, but I've read that I should avoid Get-Content so I am using StreamReader. It is still much too slow:
function append-comma{} #helper function to append the correct amount of commas to each line
$separator = '|'
$infile = "\large_data.csv"
$outfile = "new_file.csv"
$target_file_in = New-Object System.IO.StreamReader -Arg $infile
If ($header -eq 'TRUE') {
$firstline = $target_file_in.ReadLine() #skip header if exists
}
while (!$target_file_in.EndOfStream ) {
$line = $target_file_in.ReadLine()
$a = $line.split($separator)[0].trim()
$b = ""
$c = ""
if ($dataType -eq 'ECN'){$a = $a.padleft(15,'0')}
if ($line.split($separator)[1].length -gt 0){$b = $line.split($separator)[1].trim()}
if ($line.split($separator)[2].length -gt 0){$c = $line.split($separator)[2].trim()}
$line = $a +',"'+$b+'","'+$c +'"'
$line -replace '(?m)"([^,]*?)"(?=,|$)', '$1' |append-comma >> $outfile
}
$target_file_in.close()
I am building this for other people on my team and wanted to add a gui using this guide:
http://blogs.technet.com/b/heyscriptingguy/archive/2014/08/01/i-39-ve-got-a-powershell-secret-adding-a-gui-to-scripts.aspx
Is there a faster way to do this in Powershell?
I wrote a script using Linux bash(Cygwin64 on Windows) and a separate one in Python. Both ran much faster, but I am trying to script something that would be "approved" on a Windows Platform.
All that splitting and replacing costs you way more time than you gain from the StreamReader. Below code cut execution time to ~20% for me:
$separator = '|'
$infile = "\large_data.csv"
$outfile = "new_file.csv"
if ($header -eq 'TRUE') {
$linesToSkip = 1
} else {
$linesToSkip = 0
}
Get-Content $infile | select -Skip $linesToSkip | % {
[int]$a, [string]$b, [string]$c = $_.split($separator)
'{0:d15},"{1}",{2},,,,,,,,,,,,,' -f $a, $b.Trim(), $c.Trim()
} | Set-Content $outfile
How does this work for you? I was able to read and process a 35MB file in about 40 seconds on a cheap ole workstation.
File Size: 36,548,820 bytes
Processed In: 39.7259722 seconds
Function CheckPath {
[CmdletBinding()]
param(
[Parameter(Mandatory=$True,
ValueFromPipeline=$True)]
[string[]]$Path
)
BEGIN {}
PROCESS {
IF ((Test-Path -LiteralPath $Path) -EQ $False) {Write-host "Invalid File Path $Path"}
}
END {}
}
$infile = "infile.txt"
$outfile = "restult5.txt"
#Check File Path
CheckPath $InFile
#Initiate StreamReader
$Reader = New-Object -TypeName System.IO.StreamReader($InFile);
#Create New File Stream Object For StreamWriter
$WriterStream = New-Object -TypeName System.IO.FileStream(
$outfile,
[System.IO.FileMode]::Create,
[System.IO.FileAccess]::Write);
#Initiate StreamWriter
$Writer = New-Object -TypeName System.IO.StreamWriter(
$WriterStream,
[System.Text.Encoding]::ASCII);
If ($header -eq $True) {
$Reader.ReadLine() |Out-Null #Skip First Line In File
}
while ($Reader.Peek() -ge 0) {
$line = $Reader.ReadLine() #Read Line
$Line = $Line.split('|') #Split Line
$OutPut = "$($($line[0]).PadLeft(15,'0')),`"$($Line[1])`",$($Line[2]),,,,,,,,,,,,"
$Writer.WriteLine($OutPut)
}
$Reader.Close();
$Reader.Dispose();
$Writer.Flush();
$Writer.Close();
$Writer.Dispose();
$endDTM = (Get-Date) #Get Script End Time For Measurement
Write-Host "Elapsed Time: $(($endDTM-$startDTM).totalseconds) seconds" #Echo Time elapsed
Regex is fast:
$infile = ".\large_data.csv"
gc $infile|%{
$x=if($_.indexof('|')-ne$_.lastindexof('|')){
$_-replace'(.+)\|(.+)\|(.+)',('$1,"$2",$3'+','*12)
}else{
$_-replace'(.+)\|(.+)',('$1,"$2"'+','*14)
}
('0'*(15-($x-replace'([^,]),.+','$1').length))+$x
}
I have another approach. Let powershell read the input file as a csv file, with a pipe character as delimiter. Then format the output the way you want it. I have not tested this for speed with large files.
$infile = "\large-data.csv"
$outfile = "new-file.csv"
import-csv $infile -header id,addr,zip -delimiter "|" |
% {'{0},"{1}",{2},,,,,,,,,,,,,' -f $_.id.padleft(15,'0'), $_.addr.trim(), $_.zip} |
set-content $outfile