Conversion from CSV to TSV with content changes - powershell

I need to change CSV File to TSV, and also remove line breaks and double quotes.
Here's the code:
$filePath = "C:\Users\at1704171\Documents\Infinity Scorecard PBIX\converter"
$mkdir = New-Item -ItemType Directory -Force -Path (Join-Path -Path $filePath -ChildPath 'converted')
$files = Get-ChildItem (Join-Path -Path $filePath -ChildPath "*") -Include *.csv
$sep = "`t"
$ext = '.tsv'
foreach($file in $files)
{
$filename = -Join($mkdir,"\",(Get-Item $file).BaseName,$ext)
Import-Csv $file |
ConvertTo-Csv -NoTypeInformation -Delimiter $sep |
% { $_.Replace("`r"," ").Replace("`n"," ").Replace('"',"") } |
Out-File -FilePath $filename -Encoding utf8
}
it's basically converting a CSV File to TSV, but also removing line breaks and double quotes. However I noticed that there are some "tabs" (`t) within the string so I needed to insert another line between "Import" and "Convert" to replace those "tabs" by a space
I do not understand how the syntax works so I literally copied the line below "Convert" since it executes the same function and did this, but it gives an error
$filePath = "C:\Users\at1704171\Documents\Infinity Scorecard PBIX\converter"
$mkdir = New-Item -ItemType Directory -Force -Path (Join-Path -Path $filePath -ChildPath 'converted')
$files = Get-ChildItem (Join-Path -Path $filePath -ChildPath "*") -Include *.csv
$sep = "`t"
$ext = '.tsv'
foreach($file in $files)
{
$filename = -Join($mkdir,"\",(Get-Item $file).BaseName,$ext)
Import-Csv $file |
% { $_.Replace("`t"," ") } | --this is the line I added
ConvertTo-Csv -NoTypeInformation -Delimiter $sep |
% { $_.Replace("`r"," ").Replace("`n"," ").Replace('"',"") } |
Out-File -FilePath $filename -Encoding utf8
}
anybody's help is greatly appreciated here, thank you guys

Related

Powershell split file name and export to csv

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

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 }

Why doesn't this create a file on the destination server?

I recently did a storage migration and we had about 700 files that failed to migrate out of around 7 million (we need to purge some files, I know). I wrote the script below that is supposed to look at the corresponding file on the destination, compare the date values and if the file doesn't exist or has an older date, it's supposed to copy it over. Unfortunately, it's not copying it over. I don't get any errors but the file doesn't land on the destination. What am I doing wrong?
Also, I originally tried to grab the entire directory but it choked on the volume of files so that's why it parses each directory in turn instead.
$toplvl = "D:\Users\"
$folders = Get-ChildItem -Path $toplvl -Directory
$file = ""
$folders | ForEach-Object {
$original = $_.FullName
$dest = $_.FullName.Replace("D:","\\NewFileServer\D$")
$OutputFile = $_.FullName.Replace($toplvl,"D:\filelist-")
$FirstFind=0 #used to create a header in the output file
# Get all files under $original, filter out directories
$filelist = Get-ChildItem -Recurse $original | Where-Object { -not $_.PsIsContainer }
Write-Host $original #write directories to host to track progress
$filelist | ForEach-Object {
## Check if the file (from $original) exists with the same path in $dest
If (Test-Path ($_.FullName.Replace($original,$dest) ) ) {
## the file from $original has a match in $dest
$file = Get-Childitem -Path $_.FullName.Replace($original,$dest)
If ($_.LastWriteTime -gt $file.LastWriteTime) {
## file from $original is newer than $dest
If ( -Not ($FirstFind)) {Add-Content -Path $OutputFile -Value "Original File, Date"}
$FirstFind = 1
Add-Content -Path $OutputFile -Value $_.FullName -NoNewline
Add-Content -Path $OutputFile -Value "," -NoNewline
Add-Content -Path $OutputFile -Value $_.LastWriteTime
Copy-Item -Path $_.FullName -Destination $file.FullName
}
else {
## file from $original is same or older than $dest; can remove else statement
}
}
else {
## the file from $original is missing from $dest
If ( -Not ($FirstFind)) {Add-Content -Path $OutputFile -Value "Original File, Date"}
$FirstFind = 1
Add-Content -Path $OutputFile -Value $_.FullName -NoNewline
Add-Content -Path $OutputFile -Value "," -NoNewline
Add-Content -Path $OutputFile -Value $_.LastWriteTime
Copy-Item -Path $_.FullName -Destination $_.FullName.Replace($original,$dest)
}
}
}
Hopefully I didn't mess this up copying it over - it's my first time posting and I'm still figuring out the formatting.

Out-File path format is not supported

I am grabbing the last line of a file and outputing it in another file with the same name with a "t" prefix but an errors comes up.
$path = 'D:\files\'
$inc = #("*txt_*")
$exc = #("*csv_*")
$List = Get-ChildItem -Path $path -recurse -include $inc -exclude $exc
foreach ($item in $List) {
Get-Content $item.Fullname -Tail 1 | Out-File -Encoding Ascii $path"t-"$item
}
However, if I dont prepend the file name it works fine.
Get-Content $item.Fullname -Tail 1 | Out-File -Encoding Ascii $path"t-"
What is wrong with this?
Prepend the filename with T- and build the destination path from the folder name and the modified filename:
Get-ChildItem -Path $path -Recurse -Include $inc -Exclude $exc | ForEach-Object {
$dst = Join-Path $_.Directory.FullName ($_.Name -replace '^', 'T-')
Get-Content $_.FullName -Tail 1 | Set-Content $dst -Encoding ascii
}

Powershell - Write filename into same file

I have a lot of .csv Files and I want to write the filename into the same file, at the end of the last position.
For example in C:\CSV I have:
P0_0050569F52981EE39CEF8C857147E850.csv
P0_0050569F52981EE39CEF8D4825092850.csv
P0_0050569F52981EE39CEF8EE13B954850.csv
...and another thousand more of these files
In every one of this files I have some content:
P0_0050569F52981EE39CEF8C857147E850.csv = 365013;253;9001
I want to transform this: 365013;253;9001 to this:
365013;253;9001;
P0_0050569F52981EE39CEF8C857147E850.csv
I cannot find the error...
Get-ChildItem -Filter "*.csv" -Path "C:\CSV" -Recurse | % {
#Open file
$reader = New-Object System.IO.StreamReader $_.FullName
#Ignore first line
$reader.ReadLine() | out-null
#Get name
$filename = $filename
#Write
Add-Content ";" $filename
#Close stream
$reader.Close()
}
MickyB's option should work. Here's another way to do it:
Get-ChildItem -Filter "*.csv" -Path "C:\CSV" -Recurse | foreach {$contents = get-content $_.fullname; $contents +=";"+"`r`n"+$_.name; Set-Content $_.fullname -Value $contents }
This will happen the filename at the end of each CSV.
Get-ChildItem -Filter "*.csv" -Path "C:\CSV" -Recurse | % {
(";"+"`r`n"+$_.name) | Out-File -FilePath $_.fullname -Append
}