I am looking for some script in PowerShell that will compare the date present in an inside text file as content and compare if that date is >today`+15 days then print the file name.
Also, if that script can compare the date as mentioned above along with the other string if both conditions are matching then print the file name.
The below command gives me the output for those which have matching string same as hello and was created 30 days back. But now I want to fulfill the above two conditions no matter when the file was created.
Get-ChildItem -Path C:\Users\vpaul\Downloads\functional-script\*.txt -Recurse | Select-String -Pattern 'Hello', 'Hell' | Where CreationTime -lt (Get-Date).AddDays(-6)| Export-Csv C:\Users\vpaul\Downloads\functional-script\File_Name.csv -NoTypeInformation
The output from Select-String doesn't have a CreationTime property, which is why your filtering fails - CreationTime doesn't resolve to anything so it's always "less than" any value you provide.
Either do the filtering on CreationTime before piping to Select-String:
Get-ChildItem ... |Where-Object CreationTime -lt (Get-Date).AddDays(-6) |Select-String 'Hell' | ...
Or use the Path property on the output from Select-String to look up the files attributes again:
Get-ChildItem ... |Select-String 'Hell' |Where-Object {(Get-ItemPropertyValue -LiteralPath $_.Path -Name CreationTime) -lt (Get-Date).AddDays(-6)} |...
Since it looks like you're trying to get and compare a date from a matched text string inside the file, as well as CreationTime file attribute... +15 Days and -6 Days respectively...
Example Text file Content:
Hello 4/1/2021
You could try something similar to this:
$ALL_RECURSED_TXTs = Get-ChildItem -Path '[Folder to Recurse]\*.txt' -Recurse | Where-Object { $_.CreationTime -lt (Get-Date).AddDays(-6) };
foreach($File in $ALL_RECURSED_TXTs) {
Get-Content -Path $File.FullName | Select-String -Pattern 'Hello', 'Hell' |
ForEach-Object {
# Find a RegEx match for your Date String that is in the File
$_ -match 'Hello\s(\d+\/\d+\/\d{4}).*' | Out-Null;
if((Get-date($matches[1])) -gt ((Get-Date).AddDays(15))) {
"$($File.FullName)" | Out-File -FilePath '[Path to Output]\MyPrintedFileNames.txt' -Append;
}
}
}
If you want to see your matched lines in your outfile...
"$_ : $($File.FullName)" | Out-File -FilePath '[Path to Output]\MyPrintedFileNames.txt' -Append;
"but now I want to fulfill the above two conditions no matter when the file was created."
Scrap the Where-Object filter on Get-ChildItem if you want all txt files.
Edit: Getting confused again. Lol. If your txt file date string is not on same line as your "Hello|Hell" it'll get more complex. Good Luck!
Related
Lets say I have a bunch of text files with people's names, that all have this as the content:
number
I want to replace "number" with a value from a CSV or text file, sequentially, and based on the file name. CSV has two columns, name and number:
Joe 5551011000
Gary 5551011001
Clark 5551011002
So I want to find the text file named Joe, and replace the "number" with "5551011000", and the text file named Gary, and replace "number" with "5551011001".
Thank you!
I didn't get too far:
Get-ChildItem "C:\test\*.txt" -Recurse | ForEach-Object -Process {
(Get-Content $_) -Replace 'changeme', 'MyValue' | Set-Content $_
}
This gets me party there, but I don't know how to find a specific file, then replace "number" in that file with the correct value that matches the name.
I also tried a different approach, with manual entry, and it works, but I need it to just be automated:
get-childitem c:\Marriott -recurse -include *.txt |
select -expand fullname |
foreach {
$new = Read-Host 'What is the new value you want for ' $_
(Get-Content $_) -replace 'number',$new |
Set-Content $_
}
I would convert your CSV to a hashtable, then this gets pretty simple.
$ReplaceHT = #{}
Import-Csv c:\path\to\file.csv -Delimiter ' ' -Header 'FileName','Number' | ForEach-Object {$ReplaceHT.add($_.FileName,$_.Number)}
Get-ChildItem c:\Marriott -recurse -include *.txt -PipelineVariable 'File'|Where{$_.name -in $ReplaceHT.Keys} |ForEach-Object{
(Get-Content $File.FullName) -replace 'changeme', $ReplaceHT[$File.Name] | Set-Content $File.FullName
}
I am being forced to use Powershell because of my work. I have used it to do a couple of things but one of my codes is now trash because I have to update a string in a file to include a year that is in a second file. Here is what I'm working with:
File1: Contains a few strings but in there is 48 strings that say:
Jenga_Sequence-XXXX.consensus_Bob_0.6_quality_20
The main point of the string is Sequence-XXXX, sorry for the random place holders.
File2: is a table that has the strings:
John/USA/Sequence-XXXX/Year
I need to replace the strings in File1 with the corresponding Strings in File2.
Sample Text of File1:
Jenga_Sequence-0001.consensus_Bob_0.6_quality_20
AAAAAAAAAAAAAAAAAAAAAAAAA
Jenga_Sequence-0002.consensus_Bob_0.6_quality_20
aaaaaaaaaaaaaaaaaaaaaaaaa
Jenga_Sequence-0003.consensus_Bob_0.6_quality_20
bbbbbbbbbbbbbbbbbbbbbbbbb
Jenga_Sequence-0004.consensus_Bob_0.6_quality_20
BBBBBBBBBBBBBBBBBBBBBBBBB
Jenga_Sequence-0005.consensus_Bob_0.6_quality_20
QQQQQQQQQQQQQQQQQQQQQ
Sample Table of File2:
|Sequence_ID|Date|
|---------------------------|----------|
|John/USA/Sequence-0003/2020|10/11/2020|
|John/USA/Sequence-0001/2021|1/5/2021|
|John/USA/Sequence-0005/2021|1/10/2021|
|John/USA/Sequence-0004/2020|12/23/2020|
|John/USA/Sequence-0002/2021|1/6/2021|
So, I need a Powershell code that replaces
Jenga_Sequence-0001.consensus_Bob_0.6_quality_20 with John/USA/Sequence-0001/2021,
Jenga_Sequence-0002.consensus_Bob_0.6_quality_20 with John/USA/Sequence-0002/2021,
Jenga_Sequence-0003.consensus_Bob_0.6_quality_20 with John/USA/Sequence-0003/2020, and so on. There are typically 48 of these in a file.
My previous code simple replaced "Jenga_" with "John/USA/" and ".consensus_Bob_0.6_quality_20" with "/2020" but now that we are seeing "/2021" the static code will not work.
I am still open to replacing pieces of the string and having a code that sets the year replacement to the correct year.
That was the angle I was doing a broad search on but I could never find anything specific enough to help.
Any help will be appreciated!
EDIT: Here is the part of my previous code that dealt with the finding and replacing, even though I feel it needs to be trashed:
$filePath = 'Jenga_Combined.txt'
$tempFilePath = "$env:TEMP\$($filePath | Split-Path -Leaf)"
$find = 'Jenga_'
$replace = 'John/USA/'
$find2 = '.consensus_Bob_0.6_quality_20'
$replace2 = '/2020'
(Get-Content -Path $filePath) -replace $find, $replace -replace $find2, $replace2 | Add-Content -Path $tempFilePath
Remove-Item -Path $filePath
Move-Item -Path $tempFilePath -Destination $filePath
EDIT2: The "Real Data" from file2. File2 is a Tab Delimited .txt file which makes it not "look great" when copy and pasting. Hopefully this helps. File1 is exactly like above (although the AAAAA stuff is roughly 30,000 letters long)
Sequence_ID date
John/USA/Sequence-0003/2020 2020-10-11
John/USA/Sequence-0001/2021 2021-01-05
John/USA/Sequence-0005/2021 2021-01-10
John/USA/Sequence-0004/2020 2020-12-23
John/USA/Sequence-0002/2021 2021-01-06
Dan
The common factor here is the Sequence_ID number in both files.
You can do this like:
$csvData = Import-Csv -Path 'D:\Test\File2.txt' -Delimiter "`t"
$result = switch -Regex -File 'D:\Test\Jenga_Combined.txt' {
'^Jenga_Sequence-(\d+).*' {
$replace = $csvData | Where-Object { $_.Sequence_ID -like "*Sequence-$($matches[1])*" }
if (!$replace) { Write-Warning "No corresponding Sequence_ID $($matches[1]) found!"; $_ }
else { $replace.Sequence_ID }
}
default { $_ }
}
# output on screen
$result
# output to new file
$result | Set-Content -Path 'D:\Test\Jenga_Combined_NEW.txt' -Force
Output on screen:
John/USA/Sequence-0001/2021
AAAAAAAAAAAAAAAAAAAAAAAAA
John/USA/Sequence-0002/2021
aaaaaaaaaaaaaaaaaaaaaaaaa
John/USA/Sequence-0003/2020
bbbbbbbbbbbbbbbbbbbbbbbbb
John/USA/Sequence-0004/2020
BBBBBBBBBBBBBBBBBBBBBBBBB
John/USA/Sequence-0005/2021
QQQQQQQQQQQQQQQQQQQQQ
Of course, you need to change the file paths to match your environment
I need to create a csv file out of values that are spread over many txt files. Here is an example for one of the txt files (they are all formatted the same way and stored in one folder, lets say c:\user\txtfiles):
System: asdf
Store: def
processid: 00001
Language: english
prodid: yellowshoes12
email: asdf#asdf.com
prodid: blueshoes34
some
other
text blabla
The result csv should look like this (i added values from another sample txt just to make it clear):
processid, prodid
00001, yellowshoes12
00001, blueshoes34
00002, redtshirt12
00002, greensocks34
That means that every product ID in the txt should be assigned to the one processid in the txt and added as single line to the csv.
I tried to reach the result as follows:
$pathtofiles = Get-ChildItem c:\user\txtfiles | select -ExpandProperty FullName
$parsetxt = $pathtofiles |
ForEach {
$orderdata = Import-Csv $_ |
Where-Object {($_ -like '*processid*') -or ($_ -like '*prodid*')} |
foreach {
write-output $orderdata -replace 'processid: ','' -replace 'prodid: ',''
}
}
$orderdata
So my intention was to isolate the relevant lines, delete everything that is not wanted, assign the values to variables and build a table out of it. One problem is that if I replace $orderdata from the end of the code into the end of the first foreach-loop nothing is printed. But after deliberating quite a while I am not sure if my approach is a good one anyway. So any help would be very appreciated!
Daniel
I think this is best done using a switch -Regex -File construct while iterating over the files in your folder.
# get the files in the folder and loop over them
$result = Get-ChildItem -Path 'c:\user\txtfiles' -Filter '*.txt' -File | ForEach-Object {
# the switch processes each line of a file and matches the regex to it
switch -Regex -File $_.FullName {
'^processid:\s+(\d+)' { $id = $matches[1] }
'^prodid:\s+(\w+)' { [PsCustomObject]#{'processid' = $id; 'prodid' = $matches[1]}}
}
} | Sort-Object processid, prodid
# output on console screen
$result
# output to CSV file
$result | Export-Csv -Path 'c:\user\txtfiles\allids.csv'
Result on screen:
processid prodid
--------- ------
00001 blueshoes34
00001 yellowshoes12
00002 greenshoes56
00002 purpleshoes88
I have a folder of spreadsheets which all start with "WEEK COMM" and then the date. For example "WEEK COMM 24-12-2018". What I am looking to do is a script that finds the latest file, makes a copy of it in the SAME folder, and changes the date in the filename by adding 7 days.
So far I have got this, which successfully locates the most up to date file, and copies it as "WEEK COMM TEST", but I am unable to find anything about adding a date to the filename.
Get-ChildItem -Path "\\DESKTOP-88SIUP6\Users\User\Desktop\Shared\STOCK ORDERS\2018" |
Sort-Object -Property CreationTime -Descending |
Select-Object -First 1 |
Copy-Item -Destination "\\DESKTOP-88SIUP6\Users\User\Desktop\Shared\STOCK ORDERS\2018\WEEK COMM TEST.xlsx" -Force
Could anyone please help me?
this will capture the string date from the file .BaseName property, convert it to a [datetime] object, add 7 days, convert that to a date string in your [backwards [grin]] format, and then replace the old date string with the new date string in the .FullName of the file.
that should make the rename process pretty direct & easy. [grin]
if you can, you would likely have a rather easier time if you switched to the more logical, properly sortable yyyy-MM-dd format. you may not be able to do so, but it's worth trying ...
$FileName = [System.IO.FileInfo]'WEEK COMM 24-12-2018.xlsx'
$FN_StringDate = $FileName.BaseName.Split(' ')[2]
$FN_Date = [datetime]::ParseExact($FN_StringDate, 'dd-MM-yyyy', $Null)
$NewFN_StringDate = $FN_Date.AddDays(7).ToString('dd-MM-yyyy')
$NewFileName = $FileName.FullName -replace $FN_StringDate, $NewFN_StringDate
$FileName.FullName
$NewFileName
output [old, then new] ...
D:\Data\Scripts\WEEK COMM 24-12-2018.xlsx
D:\Data\Scripts\WEEK COMM 31-12-2018.xlsx
edit to add a very specific example. it's untested since i haven't any such location ... that is why the -WhatIf is there. [grin]
$SourceDir = '\\DESKTOP-88SIUP6\Users\User\Desktop\Shared\STOCK ORDERS\2018'
Get-ChildItem -Path $SourceDir |
Sort-Object -Property CreationTime -Descending |
Select-Object -First 1 |
ForEach-Object {
$FN_StringDate = $_.BaseName.Split(' ')[2]
$FN_Date = [datetime]::ParseExact($FN_StringDate, 'dd-MM-yyyy', $Null)
$NewFN_StringDate = $FN_Date.AddDays(7).ToString('dd-MM-yyyy')
$NewFileName = $_.FullName -replace $FN_StringDate, $NewFN_StringDate
# remove the "-WhatIf" when you are ready to do this for real
Copy-Item -LiteralPath $_.FullName -Destination $NewFileName -WhatIf
}
I have started learning powershell a couple of days ago, and I couldn't find anything on google that does what I need so please bear with my question.
I have been asked to replace some text strings into multiple files. I do not necessarily know the extension of the possible target files and I don't know their location either. So far I have managed to recursively browse into the directory (get-ChildItem -recurse) and find the string I was looking for with get-content and select-string:
Get-ChildItem -recurse | Get-Content | Select-String -pattern "dummy"
The problem is, I can see the occurences of the text I am looking for, but I don't know how to tell PS to return the path and the name for every matching files as well.
How can I get the name and location of the files that contains the expression I am looking for?
This should give the location of the files that contain your pattern:
Get-ChildItem -Recurse | Select-String "dummy" -List | Select Path
There are a variety of accurate answers here, but here is the most concise code for several different variations. For each variation, the top line shows the full syntax and the bottom shows terse syntax.
Item (2) is a more concise form of the answers from Jon Z and manojlds, while item (1) is equivalent to the answers from vikas368 and buygrush.
List FileInfo objects for all files containing pattern:
Get-ChildItem -Recurse filespec | Where-Object { Select-String pattern $_ -Quiet }
ls -r filespec | ? { sls pattern $_ -q }
List file names for all files containing pattern:
Get-ChildItem -Recurse filespec | Select-String pattern | Select-Object -Unique Path
ls -r filespec | sls pattern | select -u Path
List FileInfo objects for all files not containing pattern:
Get-ChildItem -Recurse filespec | Where-Object { !(Select-String pattern $_ -Quiet) }
ls -r filespec | ? { !(sls pattern $_ -q) }
List file names for all files not containing pattern:
(Get-ChildItem -Recurse filespec | Where-Object { !(Select-String pattern $_ -Quiet) }).FullName
(ls -r filespec | ? { !(sls pattern $_ -q) }).FullName
This is how I would do it, you don't need get-content:
ls -r | Select-String dummy | select line,path
or
ls -r | Select-String dummy | fl *
To see what the different properties are...
This is faster. The second argument is -filter:
ls -r . *.bat | select-string netsh
ls -r -path . -filter *.bat | select-string netsh
This will display the path, filename and the content line it found that matched the pattern.
Get-ChildItem -Path d:\applications\*config -recurse | Select-String -Pattern "dummy"
Pipe the content of your
Get-ChildItem -recurse | Get-Content | Select-String -pattern "dummy"
to fl *
You will see that the path is already being returned as a property of the objects.
IF you want just the path, use select path or select -unique path to remove duplicates:
Get-ChildItem -recurse | Get-Content | Select-String -pattern "dummy" | select -unique path
I modified one of the answers above to give me a bit more information. This spared me a second query later on. It was something like this:
Get-ChildItem `
-Path "C:\data\path" -Filter "Example*.dat" -recurse | `
Select-String -pattern "dummy" | `
Select-Object -Property Path,LineNumber,Line | `
Export-CSV "C:\ResultFile.csv"
I can specify the path and file wildcards with this structures, and it saves the filename, line number and relevant line to an output file.
Get-ChildItem -r | ? {$_.psiscontainer -eq $false} | ? {gc $_.pspath |select-string -pattern "dummy"}
This will give you the full details of all files
To keep the complete file details in resulting array you could use a slight modification of the answer posted by vikas368 (which didn't seem to work well with the ISE autocomplete):
Get-ChildItem -Recurse | Where-Object { $_ | Select-String -Pattern "dummy" }
or in short:
ls -r | ?{ $_ | Select-String -Pattern "dummy" }
If you search into one directory, you can do it:
select-string -Path "c:\temp\*.*" -Pattern "result" -List | select Path
This will display a list of the full path to each file that contains the search string:
foreach ($file in Get-ChildItem | Select-String -pattern "dummy" | Select-Object -Unique path) {$file.path}
Note that it doesn't display a header above the results and doesn't display the lines of text containing the search string. All it tells you is where you can find the files that contain the string.
With PowerShell, go to the path where your files are and then type this command and replace ENTER THE STRING YOU SEARCH HERE (but keep the double quotes):
findstr /S /I /M /C:"ENTER THE STRING YOU SEARCH HERE" *.*
Have a nice day š
This Scrit worked to find a specific file in a 3 000 000
Param
(
#Define o parametro do ano a eliminar "2020"
$DateDel = '2019',
#Define o parametro do registro do ficheiro "_800" ou "_800sm" ou "_200"
$ResFile1 = '_200',
$ResFile2 = '_800',
$ResFile3 = '_800sm',
#Define o parametro da terminacao do ficheiro "_800.jpg" ou "_800sm.jpg" ou "_200.jpg"
$TypeFile = '.jpg',
#Define o parametro de onde se localizado ficheiro "C:\users\Luis.Cunha\Desktop\LuisCunha\TarefaScript\TesteFinal\TesteScript1"
$HomePath = 'C:\Users\Luis.Cunha\Desktop\LuisCunha\TarefaScript'
)
#Inicia transcriƧao de toda informaĆ§Ć£o para o ficheiro .log indicado
Start-Transcript -Path $HomePath\CountDelItems.log -NoClobber -Append
Get-ChildItem $HomePath -Recurse -File | Measure-Object | %{$_.Count}
#o Get vai buscar o ficheiro com a data e a terminacao definidas no $homepath e $tipofich atraves do caminho indicado no $path
#depois confirma os valores que foram removidos com o verbose
Get-Childitem -Path $HomePath -Recurse -force | Where-Object { !$_.PSIsContainer -and $_.name -like "????$DateDel*$ResFile1$TypeFile" } | Measure-Object | %{$_.Count}
#Get-Childitem -Path $HomePath -Recurse -force | Where-Object { !$_.PSIsContainer -and $_.name -like "????$DateDel*$ResFile1$TypeFile" } | Remove-Item -Verbose -Force
Get-ChildItem $HomePath -Recurse -File | Measure-Object | %{$_.Count}
#Termina transcriĆ§Ć£o
Stop-Transcript