How to set LastWriteTime property of a file? - powershell

I would like to change the creation date of the files that I generate with this script :
$clientname = Read-Host "Enter the client name"
$path = Read-Host "Enter the complete path of .bak files"
$time = "01-00-00"
$space = " "
for ($i = 0; $i -lt 7;$i++)
{
$date = (Get-Date).AddDays(-1-$i).ToString('yyyy-MM-dd')
New-Item -ItemType file $path$clientname$space$date$space$time.bak
}
So it gives me theses files :
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 16/08/2013 16:55 0 client 2013-08-15 01-00-00.bak
-a--- 16/08/2013 16:55 0 client 2013-08-14 01-00-00.bak
-a--- 16/08/2013 16:55 0 client 2013-08-13 01-00-00.bak
-a--- 16/08/2013 16:55 0 client 2013-08-12 01-00-00.bak
-a--- 16/08/2013 16:55 0 client 2013-08-11 01-00-00.bak
-a--- 16/08/2013 16:55 0 client 2013-08-10 01-00-00.bak
-a--- 16/08/2013 16:55 0 client 2013-08-09 01-00-00.bak
I want to modify the LastWriteTime property of each files, I want it to be the same as the date in the file name.
Example for this file "client 2013-08-15 01-00-00.bak" the LastWriteTime will be "15/08/2013 01:00"
I'm stuck and I do not how can we do that
Thank you

Not tested, but try this in your loop after you call New-Item:
$file = Get-ChildItem $path$clientname$space$date$space$time.bak
$file.LastWriteTime = (Get-Date).AddDays(-1-$i)
If you want to see a full listing of things you can do with FileInfo objects, try calling $file | gm in your powershell console. You could also view the docs on MSDN.

for ($i=0; $i -lt 7;$i++)
{
$date = (Get-Date).AddDays(-1-$i)
$filedate = $date.ToString('yyyy-MM-dd')
$file = New-Item -ItemType File $path$clientname$space$filedate$space$time.bak
$file.LastWriteTime = $date
}

Related

Recursive Looping of Text Files to find lowest level

I have some text files, basically called jobs, where a job can contain another job or series of jobs, which can contain another job or series of jobs, etc... Essentially calling the job it contains.
The idea is to iterate through the top most file, step into the next lower file and so on until we reach the "lowest level".
The script I currently use is a loop, within a loop, within a loop. If I need to reach further down, I need to add another loop. In this example, we ignore the contents of the file having "JOB" in it.
Is there a better way to loop or iterate through all this without just adding more ForEach-Objects within ForEach-Objects?
cd C:\Files
$files = Get-ChildItem -Name
$files | ForEach-Object {
$filename1 = $_
write-host "$filename1"
$step1 = Get-Content $filename1
$step1 | ForEach-Object {
$filename2 = $_
write-host "`t$filename2" #We tab to show 2nd level job is inside 1st level job
$step2 = Get-Content $filename2
$step2 | ForEach-Object {
$filename3 = $_
$write-host "`t`t$filename3"
$step3 = Get-Content $filename3
$step3 | ForeEach-Object {#keep adding loops}
}
}
}
The jobs/files are contained all in a single directory as:
FILE1A
FILE1B
FILE1C
FILE2
FILE3
FILE4
etc..
Content of each file may look like:
JOB FILE1B
No limit to how many "JOB ???" may be contained inside the file.
There really is no convention to the naming of these files/jobs. When running the script, the result should look like this:
FILE1A
FILE1B
FILE1C
FILE2
FILE3
FILEXYZ
FILEZYX
FILE123
FILEABC
As the others in comments have mentioned, one might use recursion to accomplish this.
I hope I understood the question in my mock up.
I have some files that look like this below, some containing lines with paths to other files and some not (0 length empty files)
Directory: C:\temp\powershell\recursive_tests
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 18.08.2021 19:31 133 A1.txt
-a--- 18.08.2021 19:14 0 A1a.txt
-a--- 18.08.2021 19:31 133 A1b.txt
-a--- 18.08.2021 19:18 0 A1b1.txt
-a--- 18.08.2021 19:18 0 A1b2.txt
-a--- 18.08.2021 19:18 0 A1b3.txt
-a--- 18.08.2021 19:14 0 A1c.txt
-a--- 18.08.2021 19:31 133 B1.txt
-a--- 18.08.2021 19:31 133 B1a.txt
-a--- 18.08.2021 19:18 0 B1a1.txt
-a--- 18.08.2021 19:18 0 B1a2.txt
-a--- 18.08.2021 19:18 0 B1a3.txt
-a--- 18.08.2021 19:14 0 B1b.txt
-a--- 18.08.2021 19:31 133 B1c.txt
-a--- 18.08.2021 19:18 0 B1c1.txt
-a--- 18.08.2021 19:18 0 B1c2.txt
-a--- 18.08.2021 19:18 0 B1c3.txt
As an example A1.txt looks like this
C:\temp\powershell\recursive_tests\A1a.txt
C:\temp\powershell\recursive_tests\A1b.txt
C:\temp\powershell\recursive_tests\A1c.txt
I imagine the code to process through them could look something like this
function Get-FileInFile {
param(
[string[]]$Paths,
$Level = 0
)
foreach ($path in $Paths) {
Write-Host "$("`t" * $Level)$Path"
$lines = Get-Content -Path $Path
$newLevel = $Level + 1
$lines | ForEach-Object {
get-fileinfile -Path $_ -Level $newLevel
}
}
}
Output
PS C:\temp\powershell\recursive_tests> get-fileinfile 'C:\temp\powershell\recursive_tests\A1.txt', 'C:\temp\powershell\recursive_tests\B1.txt'
C:\temp\powershell\recursive_tests\A1.txt
C:\temp\powershell\recursive_tests\A1a.txt
C:\temp\powershell\recursive_tests\A1b.txt
C:\temp\powershell\recursive_tests\A1b1.txt
C:\temp\powershell\recursive_tests\A1b2.txt
C:\temp\powershell\recursive_tests\A1b3.txt
C:\temp\powershell\recursive_tests\A1c.txt
C:\temp\powershell\recursive_tests\B1.txt
C:\temp\powershell\recursive_tests\B1a.txt
C:\temp\powershell\recursive_tests\B1a1.txt
C:\temp\powershell\recursive_tests\B1a2.txt
C:\temp\powershell\recursive_tests\B1a3.txt
C:\temp\powershell\recursive_tests\B1b.txt
C:\temp\powershell\recursive_tests\B1c.txt
C:\temp\powershell\recursive_tests\B1c1.txt
C:\temp\powershell\recursive_tests\B1c2.txt
C:\temp\powershell\recursive_tests\B1c3.txt
Here I pass in only the 2 top level files A1.txt and B1.txt. Since all the files exist in the same folder I cannot use Get-ChildItem and just foreach through every file or files will be processed more than once, first being called initially by me and then again when their path is encountered in the sublevel files, so instead I just pass in the 2 that I know are the roots.

Powershell using send-mailmessage

i have the below code:
$file = Get-ChildItem -Path C:\MonitorTest | where {$_.LastWriteTime -lt (Get-Date).AddHours(-4) }
$message = #{
to="sender#mail.com"
from="monitoring#mail.com"
subject="testing monitoring"
smtpserver="mail.com"
bodyashtml=$true
body="$file.Name"
}
Send-MailMessage #message
the thing i have is that on Body, using "" it prints the content of the variable $file.name in one single line. (New Text Document (2) - Copy.txt New Text Document (2).txt New Text Document (3) - Copy.txt)
if i only select $file.name and run it, it will print it in lines
New Text Document (2) - Copy.txt
New Text Document (2).txt
New Text Document (3) - Copy.txt
if i run the send-mailmessage #message, the email comes thru, but its on one line as if running only "$file.name"
these are the contents of $file:
Directory: C:\MonitorTest
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 8/13/2020 3:57 PM 0 New Text Document (2) - Copy.txt
-a---- 8/13/2020 3:57 PM 0 New Text Document (2).txt
-a---- 8/13/2020 3:57 PM 0 New Text Document (3) - Copy.txt
-a---- 8/13/2020 3:57 PM 0 New Text Document (4) - Copy.txt
-a---- 8/13/2020 3:57 PM 0 New Text Document (5) - Copy.txt
-a---- 8/13/2020 2:13 PM 0 New Text Document.txt
Can anyone help me figure this out please? im running bonkers trying to figure this out.
Thanks in advance!
You are sending as html, so you will need html line breaks <br>, which can be achieved as follows:
$filesHtml = (Get-ChildItem -Path C:\MonitorTest | where {$_.LastWriteTime -lt (Get-Date).AddHours(-4) } | Select-Object -ExpandProperty Name) -join "<br>" | Out-String
$message = #{
to="sender#mail.com"
from="monitoring#mail.com"
subject="testing monitoring"
smtpserver="mail.com"
bodyashtml=$true
body=$filesHtml
}
Send-MailMessage #message
Or you can send as text:
$files = Get-ChildItem -Path C:\MonitorTest | Where-Object {$_.LastWriteTime -lt (Get-Date).AddHours(-4) } | Select-Object -ExpandProperty Name | Out-String
$message = #{
to="sender#mail.com"
from="monitoring#mail.com"
subject="testing monitoring"
smtpserver="mail.com"
bodyashtml=$false
body=$files
}
Send-MailMessage #message

Output file does not appear from StreamWriter

I am trying to implement the code at this highly rated page https://blogs.technet.microsoft.com/gbordier/2009/05/05/powershell-and-writing-files-how-fast-can-you-write-to-a-file/ using "Method 4."
When I run the code below, it does appear to take a few seconds, but no t.txt file appears to be created. What am I missing?
PS L:\users\lit\t> Get-Content .\ttt.ps1
$s = "some text"
$stream = [System.IO.StreamWriter] "t.txt"
1..10000 | % {
$stream.WriteLine($s)
}
$stream.close()
PS L:\users\lit\t> $PSVersionTable["PSVersion"]
Major Minor Build Revision
----- ----- ----- --------
5 0 10586 117
Many thanks to #Ansgar Wiechers. The only way I could place the file into the correct directory was to produce a full path from a root. Since I wanted to put it into the current directory, (Get-Location).Path provided the directory path to which I appended the file name.
Without specifying the full path, System.IO.StreamWriter wanted to put the file into my home directory.
PS C:\Users\lit\t\booo> Get-Content .\ttt.ps1
[cmdletbinding()]
Param()
$FullPath = Join-Path (Get-Location).Path "t.txt"
Write-Verbose $FullPath
$stream = [System.IO.StreamWriter] $FullPath
Write-Verbose $stream.BaseStream.Name
1..10 | % { $stream.WriteLine($_) }
$stream.close()
PS C:\Users\lit\t\booo> .\ttt.ps1 -Verbose
VERBOSE: C:\Users\lit\t\booo\t.txt
VERBOSE: C:\Users\lit\t\booo\t.txt
PS C:\Users\lit\t\booo> Get-ChildItem
Directory: C:\Users\lit\t\booo
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 1/11/2017 5:22 PM 31 t.txt
-a---- 1/11/2017 5:21 PM 251 ttt.ps1

modify script for duplicate renamed files

Using the code below in PowerShell, I'm renaming many pictures. How do I modify the code to manage duplicates? Note; many of the photos have the SAME CreationTime value. As they occur, I need them to be output as:
yyyyMMdd-HHmm-1
yyyyMMdd-HHmm-2
yyyyMMdd-HHmm-3
etc.
Script:
Dir | Rename-Item -NewName {$_.CreationTime.toString("yyyyMMdd-HHmm") + ".jpg"}
Add more to your scriptblock to check paths and cycle through until it finds something unique:
Dir | Rename-Item -NewName {
$NewName=$_.CreationTime.toString("yyyyMMdd-HHmm") + ".jpg";
$i=1
While(Test-Path ".\$NewName"){
$NewName=$_.CreationTime.toString("yyyyMMdd-HHmm") + "-$i.jpg"
$i++
}
$NewName
}
Edit: Hm, I'm not sure why it would do that unless you didn't copy my code right. I ran it against a test folder and ended up with:
PS C:\temp\test> gci
Directory: C:\temp\test
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 10/12/2016 11:13 AM 35228885 20161012-1113.jpg
-a---- 10/12/2016 11:28 AM 31413221 20161012-1128.jpg
-a---- 10/12/2016 11:37 AM 33243498 20161012-1137.jpg
-a---- 10/12/2016 4:42 PM 2110424 20161012-1642-1.jpg
-a---- 10/12/2016 4:42 PM 3300892 20161012-1642-2.jpg
-a---- 10/12/2016 4:42 PM 3295345 20161012-1642-3.jpg
-a---- 10/12/2016 4:42 PM 101138881 20161012-1642.jpg
Edit2: Ok, fixed the issue where it can't manage more than 10 of a file with the same datetime.
try this, but modify the path C:\temp with your path directory
$listcouple=gci -File -Path "C:\temp" | select name, fullname, #{Name="Datstring";Expression={$_.CreationTime.toString("yyyyMMdd-HHmm") }} | group Datstring
foreach ($item in $listcouple)
{
if ($item.Count -gt 1)
{
$compteur=0
foreach ($value in $item.Group)
{
$compteur++
$newname= $value.Datstring + "-" + $compteur.ToString() + ".jpg"
Rename-Item -path $value.fullname -newname $newname
}
}
else
{
$newname= $item.Group[0].Datstring + ".jpg"
Rename-Item -path $item.Group[0].fullname -newname $newname
}
}

Copy-Item Not Creating All Directories

I have a directory that I want to recursively copy to anoth location for processing. It seems like the first directory is not getting created. The part of the program that does the copy is below:
# Read the source files to convert.
$lAllFiles = Get-ChildItem $lSrc -Exclude $lExcludedFiles
# Remove excluded directories
foreach ( $lExclusion in $lAllExcludedDirectories ) {
# If we have a wildcard use the -notlike operator to filter the list.
# Otherwise use an -ne operator.
if ( ($lExclusion -like '*' ) -or ($lExclusion -like '?' ) ) {
$lAllFiles = [array]$lAllFiles -notlike $lExclusion
} else {
$lAllFiles = [array]$lAllFiles -ne $lExclusion
}
}
# Start the log.
Start-Transcript -Path "$lJobLog"
# Copy the data to be converted to the conversion root.
ForEach ( $lFile in $lAllFiles ) {
Copy-Item $lFile $lCnv -Recurse -Force -ErrorAction SilentlyContinue -ErrorVariable +JobErrors -Verbose
}
.
.
.
When I compare the source and destination directories, it looks as though the first subdirectory is not created in the destination and the contents of the first sub directory are written to the destination.
As an example:
The Source:
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 1/6/2013 9:30 AM AP-LEDGER
d---- 3/12/2014 9:28 AM AP.DETAIL
d---- 8/20/2014 9:33 PM AR-LEDGER
d---- 9/3/2011 9:58 AM lost+found
-a--- 5/13/2016 9:21 PM 32768 AP-BATCH-CTRL
-a--- 5/13/2016 8:39 PM 291293184 AP-LEDGER-XREF
-a--- 9/28/2015 3:14 PM 8425472 AP.JDE
-a--- 5/13/2016 8:39 PM 150700032 AP.LINK
-a--- 5/2/2016 3:30 PM 52224 AP.QUEUES
-a--- 5/13/2016 8:17 PM 743018496 AP.SUSP
-a--- 4/30/2016 9:11 PM 51222528 ARROLLARC
-a--- 4/30/2016 9:11 PM 102404096 ARROLLFWD
-a--- 5/14/2016 3:29 AM 1016950784 A_Pa
-a--- 5/14/2016 12:37 AM 238280704 A_Ra
-a--- 5/14/2016 3:16 AM 61423616 GL-CROSS
-a--- 5/14/2016 3:16 AM 175235072 GL-INDEX
-a--- 5/14/2016 3:16 AM 21512192 G_La
-a--- 5/14/2016 3:16 AM 224661504 X_AP.SUSP
-a--- 5/14/2016 3:29 AM 150089728 X_A_Pa
-a--- 5/14/2016 12:37 AM 63578112 X_A_Ra
The Destination:
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 5/26/2016 10:53 PM AP.DETAIL
d---- 5/26/2016 10:53 PM AR-LEDGER
-a--- 5/13/2016 8:38 PM 1073737728 dat001
-a--- 5/13/2016 8:39 PM 682541056 dat002
-a--- 5/13/2016 8:39 PM 1004023808 idx001
-a--- 5/13/2016 8:37 PM 41234432 over001
Note the files in the directory should reside in the folder AP-LEDGER.
What is going on?
Does the -Recurse -Force not create the directories?
Check your Copy-Item, I've used something like this function to copy files/directories from one location to the next with exclusions.
Function Copy-Folder($Path,$DestinationPath,$Exclude = $exclude) {
# Get all the files to copy
$files = Get-ChildItem -Path $Path -Exclude $Exclude
# Copy files to destination folder.
foreach($file in $files) {
Copy-Item $file.FullName $DestinationPath -Recurse -Force
$filename = $file.Name
$copy = "$DestinationPath\$filename"
Write-Host "Copied: $filename to $copy"
}
}
You should also take a look at your logic for the removing excluded sub-directories