Powershell split file name and export to csv - powershell

I have lot of files in the folder in this nameing format "yyyy-mm-dd_Discription_$Amount.pdf" , how do I make powershell script that creates csv file with three columns (Date , Description and Amount)?
I am able to extract the full file name in the below, but I need help to split and make columns.
$Directory = "C:\path to directory"
Get-ChildItem -Path $Directory -Recurse -Force | ForEach {
[PSCustomObject]#{
Name = $_.BaseName
}
} | Export-Csv -Path "./temp.csv" -NoTypeInformation
I have tried this below
$Directory = "C:\path to directory"
Get-ChildItem -Path $Directory -Recurse -Force | ForEach {
[PSCustomObject]#{
Name = $_.BaseName
}
} | Export-Csv -Path "./temp.csv" -NoTypeInformation

This will work
$Directory = '.'
(Get-ChildItem -Path $Directory -File).BaseName | Select `
#{l='Date'; e={$_.Split('_')[0]}},
#{l='Description'; e={$_.Split('_')[1]}},
#{l='Amount'; e={$_.Split('_')[2]}} |
ConvertTo-Csv -NoTypeInformation

Related

How can I get the time and date my PowerShell script deletes a file

I am using the following script to read a list of file names which are then deleted. Is there a way can get an output of the date and time each file is deleted?
$targetFolder = "D:\" $fileList = "C:\DeleteList.txt" Get-ChildItem
-Path "$targetFolder\*" -Recurse -Include #(Get-Content $fileList) | Remove-Item -Verbose
Thanks for any help.
You could keep track of the files that are deleted and the time of deletion by outputting an object with the file's fullname and current date.
This output can then be saved as structured CSV file
$targetFolder = "D:\"
$fileList = Get-Content -Path "C:\DeleteList.txt"
$deleted = Get-ChildItem -Path $targetFolder -Recurse -Include $fileList | ForEach-Object {
# output an object with the current date and the file FullName
$_ | Select-Object #{Name = 'DeletedOn'; Expression = {(Get-Date)}}, FullName
$_ | Remove-Item -WhatIf
}
# output on screen
$deleted | Format-Table -AutoSize
# output to csv file
$deleted | Export-Csv -Path 'C:\RemovedFiles.csv' -NoTypeInformation
Remove the -WhatIf safety-switch if you are satisfied with the results shown on screen.
Would this work?
$targetFolder = "D:"
$fileList = "C:\DeleteList.txt"
$Files = Get-ChildItem -Path "$targetFolder" -Recurse -Include #(Get-Content $fileList)
# Once you have the desires files stored in the $Files variable, then run a Foreach loop.
$Obj = #() # create an array called $Obj
Foreach ($File in $Files)
{
# store info in hash table
$hash = #{
DateTime = (get-date)
fileName = $File.name
fullpath = $File.fullname
}
Write-Host "deleting file $($file.name)" -for cyan
Remove-Item $File.fullname # *** BE VERY CAREFUL!!!***
# record information in an array called $Obj
$Obj += New-Object psobject -Property $hash
}
$Obj | select fileName, DateTime | Export-csv C:\...

Powershell add text to start, end of output file

I have a folder containing multiple text files that I am combining into one file. On that output file I need to add a string to the top and the bottom of the file. I have tried using insert and I keep getting an error. The file is contained in the $Output variable
My code so far:
if(!(Test-Path -Path $PathDump)) {
# create the folder if it does not yet exist
New-Item -ItemType Directory $PathDump
}
# move all *.txt items from 'C:\RemoveFirst\txt' to 'C:\RemoveFirst\DumpARoo'
# EXCEPT the output file itself
$Path = (Get-ChildItem -Path $Path -Filter '*.txt' -File).FullName | Where-Object { $_ -ne $Output}
Move-Item -Path $Path -Destination $PathDump # move (not copy) files into new directory to concat
Get-ChildItem -Path $PathDump -Filter '*.txt' -File | ForEach-Object {
'' # Output an empty line at SOF
'---------------------------------------------------------------'
$_ | Get-Content | Select-Object -Skip 1 | Select-Object -SkipLast 1
'---------------------------------------------------------------'
'' # Output an empty line at EOF
} | Add-Content -Path $OutPut
The story continues ;)
Try this:
$Path = 'C:\RemoveFirst\*.txt'
$PathDump = 'C:\RemoveFirst\DumpARoo'
$Output = 'C:\RemoveFirst\TestingFile.txt'
if(!(Test-Path -Path $PathDump)) {
# create the folder if it does not yet exist
New-Item -ItemType Directory $PathDump
}
# move all *.txt items from 'C:\RemoveFirst\txt' to 'C:\RemoveFirst\DumpARoo'
# EXCEPT the output file itself
$Path = (Get-ChildItem -Path $Path -Filter '*.txt' -File).FullName | Where-Object { $_ -ne $Output}
Move-Item -Path $Path -Destination $PathDump # move (not copy) files into new directory to concat
# Output 'SOF'
"SOF" | Add-Content -Path $OutPut
Get-ChildItem -Path $PathDump -Filter '*.txt' -File | ForEach-Object {
# output the content of the current file
$_ | Get-Content | Select-Object -Skip 1 | Select-Object -SkipLast 1 | Add-Content -Path $OutPut
}
# Output 'EOF'
"EOF" | Add-Content -Path $OutPut

powershell / merging .txt-files into csv adding date and filename

it's me again, as i mentioned yesterday i'm new to Powershell (now 3 days) and i hope you can help me again.
What I want:
I want to merge different txt-files into one csv-file
PLUS every line which is added should start with the actual date (yyyy-mm-dd) and the filename.
Expectation_Image
WhatIamActuallyGetting_Image
So what I've got so far:
New-Item Shoppinglist_$(get-date -f yyyyMMdd_hhmm).csv -ItemType File
$txtFiles = Get-ChildItem -Name *.txt
$desiredColumns = 'Date','Filename','Substance','Information','Comment'
ForEach ($file in $txtFiles) {
$csv = Import-Csv -path $file -Delimiter "`t"
$outcsv=$csv | Select-Object $desiredColumns
#I Think the mistake is somewhere here, but i habe no idea to fix it. :(
Select-Object *, #{Name = 'Date'; Expression = {(Get-Date -format s)}}
Select-Object *, #{Name = 'Filename'; Expression = {(GetFileName)}}
$outcsv | Export-Csv Shoppinglist_$(get-date -f yyyyMMdd_hhmm).csv -NoTypeInformation -Delimiter ";" -Append
}
I hope there is someone outside in the world who can help me. :)
You are right to use calculated properties, but are overthinking this a bit.
Also, Get-ChildItem returns FileInfo or DirectoryInfo objects. (unless you specify switch -Name, in that case it returns only the names of the items in the path).
These objects have useful properties, such as FullName, Name, LastWriteTime, etc.
Since you only want files returned, you can use the -File switch.
This assumes both input files have the exact same columns as in your example:
# the folder where the input files are and where the output csv file should be saved
$path = 'D:\Test'
$today = '{0:yyyy-MM-dd}' -f (Get-Date)
$txtFiles = Get-ChildItem -Path $path -Filter '*.txt' -File
$csv = foreach ($file in $txtFiles) {
Import-Csv -Path $file.FullName -Delimiter "`t" |
Select-Object #{Name = 'Date'; Expression = {$today}},
#{Name = 'Filename'; Expression = {$file.Name}}, *
}
$fileOut = Join-Path -Path $path -ChildPath ('Shoppinglist_{0:yyyyMMdd_HHmm}.csv' -f (Get-Date))
$csv | Export-Csv -Path $fileOut -Delimiter ";" -NoTypeInformation
This assumes both input files have at least the 3 desired columns: 'Substance','Information' and 'Comment'
# the folder where the input files are and where the output csv file should be saved
$path = 'D:\Test'
$today = '{0:yyyy-MM-dd}' -f (Get-Date)
$txtFiles = Get-ChildItem -Path $path -Filter '*.txt' -File
$csv = foreach ($file in $txtFiles) {
Import-Csv -Path $file.FullName -Delimiter "`t" |
Select-Object #{Name = 'Date'; Expression = {$today}},
#{Name = 'Filename'; Expression = {$file.Name}},
Substance, Information, Comment
}
$fileOut = Join-Path -Path $path -ChildPath ('Shoppinglist_{0:yyyyMMdd_HHmm}.csv' -f (Get-Date))
$csv | Export-Csv -Path $fileOut -Delimiter ";" -NoTypeInformation
If you are using a PowerShell version below 3.0, you cannot use the -File switch. Instead then use: $txtFiles = Get-ChildItem -Path $path -Filter '*.txt' | Where-Object { !$_.PSIsContainer }

Count the number of files in the directory as well as the number of folders

Currently , I can export the list to a text file and separate them by share name.
My question is : I want to be able to count the number of files in the directory as well as the number of folders into a separate text file.
I'd like to do in this format for text file , $hostname-$sharename-count.txt
For example:
My desired output:
1000 #Folder count
150 #File count
Here is what I have so far:
$outputDir = 'C:\Output'
$Shares = Get-WmiObject Win32_Share -Filter "not name like '%$'"
$re = ($Shares | ForEach-Object {[Regex]::Escape($_.Path)}) -join '|'
foreach ($Share in $Shares) {
$result = (Get-ChildItem -Path $Share.Path -File -Recurse | Select-Object -Expand FullName) -replace "^($re)\\"
# output the results per share in a text file
$fileOut = Join-Path -Path $outputDir -ChildPath ('{0}-{1}.txt' -f $env:COMPUTERNAME, $Share.Name)
$result | Out-File -FilePath $fileOut -Force
}
You can simply expand the code you have like below:
$outputDir = 'C:\Output'
$Shares = Get-WmiObject Win32_Share -Filter "not name like '%$'"
$re = ($Shares | ForEach-Object {[Regex]::Escape($_.Path)}) -join '|'
foreach ($Share in $Shares) {
$files = (Get-ChildItem -Path $Share.Path -File -Recurse | Select-Object -Expand FullName) -replace "^($re)\\"
# output the list of files per share in a text file
$fileOut = Join-Path -Path $outputDir -ChildPath ('{0}-{1}.txt' -f $env:COMPUTERNAME, $Share.Name)
$files | Out-File -FilePath $fileOut -Force
# output the count results for files and folders per share in a text file
$folders = Get-ChildItem -Path $Share.Path -Directory -Recurse
$content = 'Folders: {0}{1}Files: {2}' -f $folders.Count, [Environment]::NewLine, $files.Count
$fileOut = Join-Path -Path $outputDir -ChildPath ('{0}-{1}-count.txt' -f $env:COMPUTERNAME, $Share.Name)
$content | Out-File -FilePath $fileOut -Force
}
P.S. You can add switch -Force to the Get-ChildItem cmdlet to also get the hidden or system files listed if there are any such files inside the shares
If you just want to have a count, you could do something like this:
$resultForFiles = (Get-ChildItem -Path $Share.Path -File -Recurse | Select-Object -Expand FullName)
$resultForFolders = (Get-ChildItem -Path $Share.Path -Directory -Recurse | Select-Object -Expand FullName)
$resultForFiles.Count | Out-File "Path" -Append
$resultForFolders.Count | Out-File "Path" -Append
The -File switch for Get-ChildItem will only get files and the -Directory will only get folders
You can do this in just one line of code
Get-ChildItem | Measure-Object -Property Mode
The property Mode from Get-ChildItem tells you if you are getting folders, files or others.
You can also use get-help Measure-Object -Examples to check some useful examples on measuring files and folders

PowerShell - searching for existing files generates empty output

I wish to search for specific files listed in searchFiles and pipe their locations to TestFileLocation.CSV. However, my current script only generates an empty CSV. What am I missing?
My TestFindFile.csv is of the form:
Name
123.pdf
321.pdf
aaa.pdf
SNIPPET
$searchFiles = Import-CSV 'C:\Data\SCRIPTS\PS1\TestFindFile.csv' -Header ("Name")
$source = 'C:\Data'
ForEach($File in $searchFiles)
{
Get-ChildItem $source -Filter $File -rec | where {!$_.PSIsContainer} | select-object FullName | export-csv -notypeinformation -delimiter '|' -path c:\data\scripts\ps1\TestFileLocation.csv
}
You were overwriting the CSV for each iteration of the loop.
$searchFiles = Import-CSV 'C:\Data\SCRIPTS\PS1\TestFindFile.csv' -Header ("Name")
$source = 'C:\Data'
$outputPath = 'c:\data\scripts\ps1\TestFileLocation.csv'
$searchFiles | ForEach-Object {
# Silently continue to try to ignore error like
# not being able to read path's which are too long
Get-ChildItem $source -Filter $_ -rec -ErrorAction SilentlyContinue | where {!$_.PSIsContainer} | select-object FullName
} | export-csv -notypeinformation -delimiter '|' -path $outputPath
Example using AlphaFS
A comment asked for an example using AlphaFS because it claims to overcome the long path issue. I'm not going into all the details, but here is how I got it to work.
# download and unzip to c:\alpahfs
# dir C:\AlphaFS\* -Recurse -File | Unblock-File
[System.Reflection.Assembly]::LoadFrom('C:\AlphaFS\lib\net451\AlphaFS.dll')
$searchFiles = Import-CSV 'C:\Data\SCRIPTS\PS1\TestFindFile.csv' -Header ("Name")
$source = 'C:\Data'
$outputPath = 'c:\data\scripts\ps1\TestFileLocation.csv'
$searchFiles | ForEach-Object {
$files = [Alphaleonis.Win32.Filesystem.Directory]::EnumerateFiles($source,'*',[System.IO.SearchOption]::AllDirectories)
$files | ForEach-Object { [PSCustomObject] #{FileName = $_} }
} | export-csv -notypeinformation -delimiter '|' -path $outputPath
# type $outputPath
If your .csv file contains the header "Name", there is no need to again declare it when running Import-Csv.
The reason the output is empty is that you are searching for an Object which contains the property Name (imported from the TestFindFile.csv). Search for $File.Name. Also pull commands outside the loop that don't need to be there:
$searchFiles | Select -ExpandProperty Name | % {
Get-ChildItem $source -Filter $_ -Recurse | where {!$_.PSIsContainer}
} | select-object FullName | export-csv -notypeinformation -delimiter '|' -path c:\data\scripts\ps1\TestFileLocation.csv