Select multiple files by file name and get content - powershell

I run this script for my monitoring system, but i want to extend the range of the aviable date.
Is there any way to get the content of multiple files with different names. Currently im only looking for one specific name pattern, for example, for all files which include a specific date like 2022-08-08*.log.
So what i want to do, is to collect all files from 7 days ago up to 1 day ago at the same time and get the content.
$backuppath = "random-name-in-logfile"
$yest = (get-date (get-date).addDays(-1) -UFormat "%Y-%m-%d")
# check for pattern in files
$path1 = Get-ChildItem `
-Path "C:\path\to\log" -Filter "$yest*.log" -recurse | `
Select-String -pattern ([regex]::escape($backuppath)) | `
Select-Object -Property Path
# transform string to usable path
$path2 = $path1 -replace ('#{Path=','') -replace ('}','')
# check for more details
$analyze = Get-Content $path2 | Select-String -pattern "Pattern" -SimpleMatch

Ok i think i got it.
It´s easier to do by setting the creation time to a limit like 1 day (or for my example 7 days)
$path1 = Get-ChildItem `
-Path "C:\path\to\log" -Filter "*.log" -recurse | `
Where-Object { $_.CreationTime -gt (Get-Date).AddDays(-7) } | `
Select-String -pattern ([regex]::escape($backuppath)) | `
Select-Object -Property Path

Related

Can get-childitem be filtered by file type and date (created in last 7 days by sytem date) at the same time? If not, how can i combine them?

I currently have a script I use to show me .dat files in certain folders. Now, I would like it to return .dat files only created in the last 7 days (from date of execution in task scheduler). I found $time=(Get-Date).AddDays(-7) in one of the questions on here and think this is my solution but not sure how to combine it with what i have currently. This is my script below.
$searchDir = "z:\G29"
$searchFile = "*.dat"
$outputDir = "d:\AuditLog\AuditLog_$(get-date -f yyyy-MM-dd).txt"
$time=(Get-Date).AddDays(-7)
$files = Get-ChildItem -Path $searchDir -Recurse -Filter $searchFile -EA SilentlyContinue |
Select CreationTime, Fullname |
format-table -wrap -autosize |
Out-File $outputDir -Append
I have added the solution I found but I seem to be missing a part. I realize now $time=(Get-Date).AddDays(-7) is just a declaration but how do i call it in the next line
$files = Get-ChildItem -Path $searchDir -Recurse -Filter $searchFile -EA SilentlyContinue |

List of files not accessed for the last 1 year in shared folder using powershell

I am trying to get a list of files in shared folder not accessed for more than one year , i gave the filter AddMonths(-12) also tried AddYears(-1) , doesnt work, list generated in csv contains file having date as current year
$time = Get-Date
$time.AddMonths(-12)
get-childitem "\\Ajay-1\" -Recurse -File -ErrorAction SilentlyContinue| Where-
Object {$_.LastAccessTime -lt $time} | select fullname,lastaccesstime |
export-csv "D:\Time\Last.csv" -notypeinfo
You'd have better luck modifying how you're handling $time
$time = (Get-Date).AddDays(-365)
$path = "C:\"
Get-ChildItem -Path $path -Recurse -Force | Where-Object {$_.LastAccessTime -lt $time} | select fullname,lastaccesstime |export-csv "D:\Time\Last.csv" -notypeinfo
Using this should achieve what you're looking for.

Is it possible to use comments in Powershell multiple line commands?

Debugging and testing multiline commands in Powershell ISE has been bugging me for years. I like having multiple line commands because they are easy to read, but they make things harder to debug. As an example, I'm using the following command to get folders older than $days (which by the way works).
$dirs = Get-ChildItem $targetDir -Directory -exclude *.ps1 `
| Where CreationTime -gt (Get-Date).AddDays(-1 * $days) `
| Sort-Object -Property LastWriteTime
I'd like to change AddDays to AddMinutes to test different result sets but I want to leave the original line in so I can easily switch back and forth. Below I copied the line I want to keep and commented it out, and on the new line changed AddDays to AddMinutes Adding a # breaks the multiline feature. Is there an easy way around this I don't have to cut my copied line and move it "out" of the command? Or is there a way to split/unsplit a command into and out of multiple lines?
$dirs = Get-ChildItem $targetDir -Directory -exclude *.ps1 `
# | Where CreationTime -gt (Get-Date).AddDays(-1 * $days) `
| Where CreationTime -gt (Get-Date).AddMinutes(-1 * $days) `
| Sort-Object -Property LastWriteTime
(above does not work due to commented out line)
Use the multiline comment syntax instead of #.
<# comment #>
This should allow you to comment text within a multi-line command.
However, this works only if you are using Powershell 2.0
As powershell expects a continuation after a | or a ,
as the last char in a line you don't need the backtick and
you could format differently, then the single line comment in a longer pipe still works:
$dirs = Get-ChildItem $targetDir -Directory -exclude *.ps1 |
# Where CreationTime -gt (Get-Date).AddDays(-1 * $days) |
Where CreationTime -gt (Get-Date).AddMinutes(-1 * $minutes) |
Sort-Object -Property LastWriteTime
your problem is the [icky, nasty] backticks. [grin] powershell knows there is more coming after a pipe ... so there is no need to add a backtick if you put the pipe at the end of the segment that is being piped. like this ...
$dirs = Get-ChildItem $targetDir -Directory -exclude *.ps1 |
# Where CreationTime -gt (Get-Date).AddDays(-1 * $days) |
Where CreationTime -gt (Get-Date).AddMinutes(-1 * $days) |
Sort-Object -Property LastWriteTime
Try this, which can be included as a multiline comment example
$dirs = Get-ChildItem $targetDir -Directory -exclude *.ps1 `
<# | Where CreationTime -gt (Get-Date).AddDays(-1 * $days) #> ` | Where CreationTime -gt (Get-Date).AddMinutes(-1 * $days) `
| Sort-Object -Property LastWriteTime

Powershell -renaming a file after copying

I'm having ongoing trouble with a script I've written that is (supposed) to do the following.
I have one folder with a number of csv files, and I want to copy the latest file with the company name into another folder, and rename it.
It is in the current format:
21Feb17070051_CompanyName_Sent21022017
I want it in the following format:
CompanyName21022017
So I have the following powershell script to do this:
## Declare variables ##
$DateStamp = get-date -uformat "%Y%m%d"
$csv_dest = "C:\Dest"
$csv_path = "C:\Location"
## Copy latest Company CSV file ##
get-childitem -path $csv_path -Filter "*Company*.csv" |
where-object { -not $_.PSIsContainer } |
sort-object -Property $_.CreationTime |
select-object -last 1 |
copy-item -Destination $csv_dest
## Rename the file that has been moved ##
get-childitem -path $csv_dest -Filter "*Company*.csv" |
where-object { -not $_.PSIsContainer } |
sort-object -Property $_.CreationTime |
select-object -last 1 | rename-item $file -NewName {"Company" + $DateStamp + ".csv"}
The file seems to copy ok, but the rename fails -
Rename-Item : Cannot bind argument to parameter 'Path' because it is null.
At C:\Powershell Scripts\MoveCompanyFiles.ps1:20 char:41
+ select-object -last 1 | rename-item $file -NewName {"CompanyName" + $DateSt ...
I think it is something to do with the order in which powershell works, or the fact it can't see the .csv in the $file variable. There are other files (text files, batch files) in the destination, in case that affects things.
Any help in where I'm going wrong would be appreciated.
As wOxxOm answered, you need to remove $file from Rename-Item as it is not defined and the cmdlet already receives the inputobject through the pipeline.
I would also suggest that you combine the two operations by passing through the fileinfo-object for the copied file to Rename-Item. Ex:
## Declare variables ##
$DateStamp = get-date -uformat "%Y%m%d"
$csv_dest = "C:\Dest"
$csv_path = "C:\Location"
## Copy and rename latest Company CSV file ##
Get-ChildItem -Path $csv_path -Filter "*Company*.csv" |
Where-Object { -not $_.PSIsContainer } |
Sort-Object -Property CreationTime |
Select-Object -Last 1 |
Copy-Item -Destination $csv_dest -PassThru |
Rename-Item -NewName {"Company" + $DateStamp + ".csv"}
You can rename and copy in a single command. Just use Copy-Item Command and give new path and name as -Destination parameter value. It will copy and rename the file. You can find an example below.
$source_path = "c:\devops\test"
$destination_path = "c:\devops\test\"
$file_name_pattern = "*.nupkg"
get-childitem -path $source_path -Filter $file_name_pattern |
Copy-Item -Destination { $destination_path + $_.Name.Split("-")[0] + ".nupkg"}

Add folder date to the foldername

I have a script which recursively modifies the "creation date" and the"modified date" of folders to match the oldest and newest files in folders (image files).
After that I want to add the creation date of each folder as a prefix to its name. I have written the code that creates the desired name but I don't know how to rename the folders.
$colFolder = Get-ChildItem -Recurse "." |
Where-Object {$_.mode -match "d"} |
Sort-Object Fullname -Descending
$VerbosePreference = "Continue"
foreach ($strFolder In $colFolder) {
Trap [Exception] {
Write-Verbose "TRAPPED:"
Write-Verbose $_.Exception.Message;
Write-Verbose $strFolder.FullName
Continue
}
$Path = $strFolder.FullName
$Folder = Get-Item $Path
# Get Newest file in folder
$strOldestTime = (Get-ChildItem $Path | Sort-Object LastWriteTime | Select-Object -First 1).LastWriteTime
$strNewestTime = (Get-ChildItem $Path | Sort-Object LastWriteTime | Select-Object -Last 1).LastWriteTime
# Change the date to match the newest file if it doesn't already
$Folder.CreationTime = $strOldestTime
$Folder.LastWriteTime = $strNewestTime
# add the date as the prefix of the folder (in which the files are)
$date = $strOldestTime.ToString('yyyy-MM-dd')
$foldername = $Folder.Name.split("\")[-1]
Write-Verbose "$date- $foldername"
#now rename the folder to above name
}
Renaming folders can be done as #onupdatecascade described in his answer.
Rename-Item -Path $Folder.FullName -NewName $newname
If you have at least PowerShell v3 (which I highly recommend) you can use the parameter -LiteralPath for the current folder path to avoid issues with special characters:
Rename-Item -LiteralPath $Folder.FullName -NewName $newname
With that said, there are a couple improvements to your code I'd like to suggest.
Get-ChildItem -Recurse ".":
Get-ChildItem uses the current working directory by default, so "." can be omitted.
Where-Object {$_.mode -match "d"}:
The objects you get from Get-ChildItem have a boolean property IsContainer that indicates whether you have a folder or not. No need to use a regex match on the mode. Also, in PowerShell v3 and newer you can omit this step entirely, because the Get-ChildItem cmdlet has an additional parameter -Directory that lists only folders.
Misused hungarian notation (pt.1):
foreach ($strFolder In $colFolder) {
The loop variable $strFolder does not contain strings, but DirectoryInfo objects. This is a prime example for why I consider hungarian notation a pointless waste of space.
Avoid unnecessary steps.
$Path = $strFolder.FullName
$Folder = Get-Item $Path
$strFolder already contains a DirectoryInfo object. The above two statements just convert it to a path string and back to a DirectoryInfo object. Simply make $Folder your loop variable (see above).
Avoid duplicate code (particularly duplicate disk operations):
$strOldestTime = (Get-ChildItem $Path | Sort-Object LastWriteTime | Select-Object -First 1).LastWriteTime
$strNewestTime = (Get-ChildItem $Path | Sort-Object LastWriteTime | Select-Object -Last 1).LastWriteTime
Instead of listing and sorting the child items multiple times run the statement just once and collect the result in a variable:
$items = Get-ChildItem $Path | Sort-Object LastWriteTime
$strOldestTime = ($items | Select-Object -First 1).LastWriteTime
$strNewestTime = ($items | Select-Object -Last 1).LastWriteTime
Also, I would simply expand the LastWriteTime property instead of running Select-Object in a subexpression:
$strOldestTime = $items | Select-Object -First 1 -Expand LastWriteTime
$strNewestTime = $items | Select-Object -Last 1 -Expand LastWriteTime
Misused hungarian notation (pt.2):
$strOldestTime and $strNewestTime contain DateTime objects, not strings.
$foldername = $Folder.Name.split("\")[-1]:
The Name property already contains the folder name without path, so there's nothing to split off.
Construct the new folder name from the date and the current name by using the format operator:
$newname = '{0:yyyy-MM-dd} - {1}' -f $oldestTime, $Folder.Name
If there's a possibility that you'll run the script multiple times you may want to remove an existing leading date from the folder name so that the dates won't "stack":
$Folder.Name -replace '^\d{4}-\d{2}-\d{2} - '
Simplified code:
$colFolder = Get-ChildItem -Recurse |
Where-Object { $_.PSIsContainer } |
Sort-Object Fullname -Descending
foreach ($folder in $colFolder) {
$items = Get-ChildItem $folder.FullName | Sort-Object LastWriteTime
$folder.CreationTime = $items | Select-Object -First 1 -Expand LastWriteTime
$folder.LastWriteTime = $items | Select-Object -Last 1 -Expand LastWriteTime
$newname = '{0:yyyy-MM-dd} - {1}' -f $folder.CreationTime, ($folder.Name -replace '^\d{4}-\d{2}-\d{2} - ')
Rename-Item -Path $folder.FullName -NewName $newname
}
or (PowerShell v3 and newer):
$colFolder = Get-ChildItem -Recurse -Directory |
Sort-Object Fullname -Descending
foreach ($folder in $colFolder) {
$items = Get-ChildItem $folder.FullName | Sort-Object LastWriteTime
$folder.CreationTime = $items | Select-Object -First 1 -Expand LastWriteTime
$folder.LastWriteTime = $items | Select-Object -Last 1 -Expand LastWriteTime
$newname = '{0:yyyy-MM-dd} - {1}' -f $folder.CreationTime, ($folder.Name -replace '^\d{4}-\d{2}-\d{2} - ')
Rename-Item -LiteralPath $folder.FullName -NewName $newname
}
Have you tried
Rename-Item oldname newname
It works for simple examples, but could break with folders nested in other folders, and recursion, because you might rename a folder before the script is done with it.
To manage that you can do them in order by length (paths to children being by definition longer than the paths of the parents). Good example here: How do I recursively rename folders with Powershell?