Prefix filename with sequential number. Be prompted (powershell) - windows

I am trying the insert a number as a prefix "n__" for each filename in the CWD (not recursively). n is a number with increments of +1, user needs to enter the first value. To number, the files must be pre-sorted in lowest-value-first order based on the filename.
$i = Read-Host 'Enter first file number'
$confirmation = Read-Host "Re-enter first file number"
if ($confirmation -eq '=') {
# proceed
}
Get-ChildItem | Sort-Object | Rename-Item -NewName { "$i+1" + "__" + $_.Name }
What I am missing at the i+ and in order to ensure that the files are sorted for numbering?
Intended result:
101__121.ext
102__211.ext
103__375.ext

# putting [int] before the variable will insure that your input is an integer and not a string
[int] $i = Read-Host 'Enter first file number'
[int] $confirmation = Read-Host "Re-enter first file number"
# Your if statement seemed to not make sense. This is my take
if ($confirmation -eq $i)
{
Get-ChildItem | Sort-Object | Foreach-Object -Process {
$NewName = '{0}__{1}' -f $i,$_.Name # String formatting e.x. 1__FileName.txt
$_ | Rename-Item -NewName $NewName # rename item
$i ++ # increment number before next iteration
}
}
else
{
Write-Warning -Message "Your input did not match"
}

Assuming files are numeric names (121.ext,211.ext,etc.)
[Int]$UserInput = Read-Host -Prompt 'Enter first file number'
[Int]$Confirmation = Read-Host -Prompt 'Re-enter first file number'
If ($Confirmation -ne $UserInput) { Exit }
$Collection = Get-ChildItem | Sort-Object -Property #{Expression={[Int]$_.BaseName}}
While (($UserInput - $Confirmation) -lt $Collection.Count)
{
$Collection[$UserInput - $Confirmation] |
Rename-Item -NewName "$($UserInput)__$($_.Name)"
$UserInput++
}

Related

Powershell file updating with future and past time

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

Replacing multiple lines in a file

I try to make, the line from the first array is read from a file and is replaced with a line from the second array, so some times with different lines. I made a script, but I do not understand why it does not work.
$OldStrings = #(
"desktopwidth:i:1440",
"desktopheight:i:900",
"winposstr:s:0,1,140,60,1596,999"
)
$NewStrings = #(
"desktopwidth:i:1734",
"desktopheight:i:990",
"winposstr:s:0,1,50,7,1800,1036"
)
$LinesArray = Get-Content -Path 'C:\temp\My Copy\Default.rdp'
$LinesCount = $LinesArray.Count
for ($i=0; $i -lt $LinesCount; $i++) {
foreach ($OldString in $OldStrings) {
foreach ($NewString in $NewStrings) {
if ($LinesArray[$i] -like $OldString) {
$LinesArray[$i] = $LinesArray[$i] -replace $OldString, $NewString
Write-Host "`nline" $i "takes on value:" $LinesArray[$i] "`n" -ForegroundColor Gray
}
}
}
}
The file is probably why it is not read at all.
After executing the script, I see only
line 2 takes on value: desktopwidth:i:1734
line 3 takes on value: desktopwidth:i:1734
line 5 takes on value: desktopwidth:i:1734
You're looking through the string arrays twice. You want to do two loops, one for each line in the file AND another for each count in the lines you're replacing. I think this should work:
$OldStrings = #(
"desktopwidth:i:1440",
"desktopheight:i:900",
"winposstr:s:0,1,140,60,1596,999"
)
$NewStrings = #(
"desktopwidth:i:1734",
"desktopheight:i:990",
"winposstr:s:0,1,50,7,1800,1036"
)
$LinesArray = Get-Content -Path 'C:\temp\My Copy\Default.rdp'
# loop through each line
for ($i=0; $i -lt $LinesArray.Count; $i++)
{
for ($j=0;$j -lt $OldStrings.Count; $j++)
{
if ($LinesArray[$i] -match $OldStrings[$j])
{
$LinesArray[$i] = $LinesArray[$i] -replace $OldStrings[$j],$NewStrings[$j]
Write-Host "`nline" $i "takes on value:" $LinesArray[$i] "`n" -ForegroundColor Gray
}
}
}
$LinesArray | Set-Content -Path 'C:\temp\My Copy\Default.rdp'
You don't need to bother checking the lines to look for matches. Since you have the replacements ready just do the replacements outright anyway. Should be faster this way as well.
$stringReplacements = #{
"desktopwidth:i:1440" = "desktopwidth:i:1734"
"desktopheight:i:900" = "desktopheight:i:990"
"winposstr:s:0,1,140,60,1596,999" = "winposstr:s:0,1,50,7,1800,1036"
}
$path = 'C:\temp\My Copy\Default.rdp'
# Read the file in as a single string.
$fileContent = Get-Content $path | Out-String
# Iterate over each key value pair
$stringReplacements.Keys | ForEach-Object{
# Attempt the replacement for each key/pair search/replace pair
$fileContent =$fileContent.Replace($_,$stringReplacements[$_])
}
# Write changes back to file.
# $fileContent | Set-Content $path
$stringReplacements is a key value hash of search and replace strings. I don't see you writing the changes back to file so I left a line on the end for you to uncomment.
You could add in checks to do the replacements still if you value the write-host lines but I figured that was for debugging and you already know how to do that.

How i can convert a txt to int in powershell

i have a txt file with this :
1230;
012;
45;
125
and i want to convert this in an int
but is doesn't work... he juste return the last number
here is my code :
$numbertxt = get-content -Path C:\mysticpath\number.txt -Raw
$numbertxt.GetType()
write-host $numbertxt
foreach ($flags in $numbertxt)
{
$integer = [int]$flags
}
echo $integer
somebody can help me ?
Sorry for my english
$numbertxt = (get-content -Path C:\mysticpath\number.txt -Raw) -split ';'
$numbertxt.GetType()
write-host $numbertxt
foreach ($flags in $numbertxt)
{
$integer = [int]$flags
echo $integer
}
First a integer can only be made of numbers so you will need to split the contents by ';'. This will make a array of strings that are numbers.
Also put the echo on the inside of the for loop will allow for it to display each number as its processed
try this method (control if it's convertible to integer before print)
$res=0;
#verbose version
(Get-Content "c:\temp\test.txt") -split ';' | where {[int]::TryParse($_, [ref] $res)} | foreach {$res}
#short version
(gc "c:\temp\test.txt") -split ';' | ?{[int]::TryParse($_, [ref] $res)} | %{$res}

Sort list of strings with starting number in powershell

i'm new to powershell so any help is much appreciated.
I have an list of strings (filenames) and they start with a number eg. "1. first file", "2. second file" ... "21. twenty-first file".
and I want to sort it in the order of the starting number. But when I do "$List | sort {$_.Name} -Unique" it will start with "1. " and then the next item is "11." instead of "2."
Please help.
Here is one way to do it:
$test = #('1. First', '2. Second', '11. Eleventh')
$sort = #()
foreach($item in $test){
$item -match '^(\d+).*'
$temp = New-Object PSCustomObject -property #{'Number' = [int]$matches[1]}
$sort += $temp
}
$sort | Sort-Object Number | Select-Object Data
Here's another option:
$col = #(
'1. first file'
'2. second file'
'11. eleventh file'
'21. twenty-first file'
)
$ht = #{}
$col | foreach {$ht[$_ -replace '\D+$'] = $_}
[int[]]$ht.keys | sort | foreach {$ht["$_"] }
1. first file
2. second file
11. eleventh file
21. twenty-first file
To simplify the previous answer a little, you could do this:
$test | Sort-Object -Property #{ Expression={[int]$_.substring(0,$_.IndexOf('.'))}; Ascending=$true }

Active Directory and Powershell

I'm currently rewriting a script that is in VB into a Powershell script.
What the script does is search our Active Directory for a user based on the script-users input.
Function PromptForName{
$nameInput = "*"
$nameInput += Read-Host ("Please enter a full or partial name.")
$nameInput += "*"
return $nameInput
}
Function FindUsers{
param ([string]$n)
$usersArray = Get-ADUser -f {DisplayName -like $n} | Select-Object Name
return $usersArray
}
This code will print out the correct list of names. What I then want to do is allow the user to choose one of those names, and have more information about that person. I'm stuck at allowing the script-user to select one of those names.
How can I prompt for another input; where the box will display a numbered list of all the names that FindUsers gave, and then return a number based on which user they chose? I'm completely lost.
This is currently how I am trying to do it, although I'm pretty sure it's completely wrong.
Function PrintUsers{
param $a
[int]$i, $j
[string]$userList
$j = 1
foreach($object in $array){
$userList += ($j + $array[$i])
$j++
}
return $userList
}
Function SelectUser{
param $list
$user = Read-Host ($list)
}
EDIT:
I have updated my functions to the following:
Function FindUsers{
param ([string]$n)
$usersArray = #(Get-ADUser -f {DisplayName -like $n} | Select-Object Name| Format-List)
return $usersArray
}
Function PrintUsers{
param ([String[]]$array)
$i
for($i = 1; $i -lt $usersArray.length; $i++){
Write-Host "$i. $($usersArray[$i-1].Name)"
}
}
The output after FindUsers is like this:
Name : xxxxx yyyyy
Name : xxxxx zzzzz
etc.
So the return of $usersArray is printing all that.
I don't want any printing until the PrintUsers function, and I want it to be in a numbered list type format like this:
1. xxxx yyyy
2. xxxx zzzz
etc.
I'm having the most difficult time figuring this out.
# get all users
$usersArray = #(Get-ADUser -f {DisplayName -like $n} )
# create menu
for($i=1; $i -le $usersArray.count; $i++){
Write-Host "$i. $($usersArray[$i-1].Name)"
}
# prompt for user number
$user = Read-Host Enter the user number to get more info
# display full info for selected user
$usersArray[$user-1] | Format-List *
Use Add-Member to add a unique identifier to each user. Let's treat processes as if they're user objects, for the sake of example:
$procs = gps;
$procs = $procs | % { $i=0; } {
Add-Member -MemberType NoteProperty -InputObject $_ -Name Number -Value $i -PassThru;
$i++;
};
$procs | select Number,Name;
$procid = Read-Host -Prompt 'Enter the number of the process you would like to operate on';
$proc = $procs | ? { $_.Number -eq $procid };
Write-Host -Object ('Operating on proc: {0}' -f $proc.Name);

Resources