I have two CSV files that don't have any unique identifiers. The number of rows of both files is always the same. I want to merge them as it is (the 2nd CSV as additional columns into the 1st CSV).
Content of file1.csv:
Server,Info
server1,item1
server1,item2
server1,item3
server2,item1
server2,item2
server2,item3
server3,item1
server3,item2
server3,item3
Content of file2.csv:
Items,ColumnA,ColumnB,ColumnC
item#1:,aa,jj,ss
item#2:,bb,kk,tt
item#3:,cc,ll,uu
item#1:,dd,mm,vv
item#2:,ee,nn,ww
item#3:,ff,oo,xx
item#1:,gg,pp,yy
item#2:,hh,qq,zz
item#3:,ii,rr,ab
Expecting output of csv file:
Server,Info,Items,ColumnA,ColumnB,ColumnC
server1,item1,item#1:,aa,jj,ss
server1,item2,item#2:,bb,kk,tt
server1,item3,item#3:,cc,ll,uu
server2,item1,item#1:,dd,mm,vv
server2,item2,item#2:,ee,nn,ww
server2,item3,item#3:,ff,oo,xx
server3,item1,item#1:,gg,pp,yy
server3,item2,item#2:,hh,qq,zz
server3,item3,item#3:,ii,rr,ab
I have search intensively in the net, but couldn't find any solution... Would really appreciate if someone can provide me some answers here...
You can use the Get-Content cmdlet to read both CSV files, iterate over it using a for-loop and use a format string to join them together. Finally, write the new file back using the Out-File cmdlet:
$file1 = Get-Content 'Path_to_file1.csv'
$file2 = Get-Content 'Path_to_file2.csv'
$content = for ($i = 0; $i -lt $file1.Length; $i++)
{
'{0},{1}' -f $file1[$i].Trim(), $file2[$i].Trim()
}
$content | out-file 'Path_to_file3.csv'
I would like to rename files and folders based on keywords found in a CSV file.
The CSV holds the search and replace keywords that will make up file and folder names.
Search | Replace
Document | DTX
Processing | PRX
Implementation | IMX
...
Not all the file names include each word in the file name.
Not all the folders will include each word in the folder name
Powershell will have to search the child item ie the folder and file
names.
If it finds the word (match) - Substitute from the CSV
I have looked at these threads to help me:
Using Powershell to recursively rename directories using a lookup file
powershell script to rename all files in directory
http://code.adonline.id.au/batch-rename-files/
I have only managed below snippet
$folder = "C:\Folders" #target folder containing files
$csv = "C:\FileNameKeywords.csv" #path to CSV file
cd ($folder);
Import-Csv ($csv) | foreach {
Rename-Item -Path $_.Path -NewName $_.Filename
}
It only replaces one at a time.
Question:
How can I recursively search and replace in file and Folder Names using a CSV as a look up or reference file.
When you have the need to look up values by other values the usual go-to data structure is a dictionary, or in PowerShell terms a hashtable. Read your CSV into a dictionary like this:
$keywords = #{}
Import-Csv $csv | ForEach-Object {
$keywords[$_.Search] = $_.Replace
}
Then traverse your folder tree and build the new filenames by replacing each key with its respective value:
Get-ChildItem $folder -Recurse | ForEach-Object {
$newname = $_.Name
foreach ($word in $keywords.Keys) {
$newname = $newname.Replace($word, $keywords[$word])
}
if ($_.Name -ne $newname) {
Rename-Item -Path $_.FullName -NewName $newname
}
}
ill give it a shot. I'm assuming search and replace are your headers in this scenario. this in addition to your $folder and $csv variables.
$csvobject=import-csv $csv
Foreach($obj in $csvobject){
$search=$obj.search
$replace=$obj.replace
get-childitem path $folder |where{$_.name -like "$($obj.search)"} | rename-item -newname {$_.name -replace "$search", "$replace"} }
The replace handles regex so u will need to make sure Any special characters are properly escaped.
I am trying to Copy Directories - folders and Sub folders to another location using a CSV file that lists the source and destination of each directory or folder to be copied.
The Contents of the CSV are as such below:
I have referenced this thread:
https://serverfault.com/questions/399325/copying-list-of-files-through-powershell
Import-CSV C:\Users\WP\Desktop\a.csv | foreach{Copy-item "$_.Source" "$_.Destination"}
Error Received
CategoryInfo : ObjectNotFound: (#{Source=C:String) [Copy-Item], DriveNotFoundException
+ FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.CopyItemCommand
The other question I have is if in the CSV I want to copy to a folder that does not exists in the destination - can I use the CSV to command powershell to create the folder?
Thank you for your advice.
PowerShell will not expand the variable and access the property of the object inside the variable if you have them placed in double quotes by default. Only the '$_' is being expanded and '.source' is being tacked on to the end of the string, so from the view of the shell, your command looks something like Copy-item "{source=C:\Users\WP\Desktop\a;Destination=C:\Users\WP\Desktop\a}.Source" "{source=C:\Users\WP\Desktop\a;Destination=C:\Users\WP\Desktop\a}.Destination", which is probably not what you mean.
Here is the syntax that should work (I also included -Recurse so that it will copy the items inside the directory as well)
Import-CSV C:\Users\WP\Desktop\a.csv | foreach{Copy-item -Path $_.Source -Destination $_.Destination -Recurse}
Note: if you want to access the properties on an object inside of double quotes, use this syntax "$($_.source)".
For a csv like this:
Source,Destination
D:\junk\test1,D:\junk\test3
D:\junk\test2,D:\junk\test4
You can use code like the following:
$csv = Import-Csv D:\junk\test.csv
$csv | ForEach-Object {
if (-not (Test-Path $_.Destination)) {
New-Item -Name $_.Destination -ItemType Directory -Force -WhatIf
}
Copy-Item $_.Source $_.Destination -Recurse -Force -WhatIf
}
Suggestions for learning more about PowerShell:
Use WhatIf to test things.
Research what each line of this code does.
Experiment with code to see what it does.
Learn and use the debugger (PowerShell ISE) to help you write better code.
Remove the WhatIf parameters from the code to have it execute for real...
If you have dozens of problems that all involve doing the same thing with each element of a list, you might want to consider getting or writing a generic CSV template expander tool, like Expand-csv. With this tool you start with a CSV file and a template, and generate a script that contains all the commands.
Sample.csv looks like this:
Source,Destination
C:\Users\WP\Desktop\a,C:\Users\WP\Desktop\c
C:\Users\WP\Desktop\b,C:\Users\WP\Desktop\d
Sample.tmplt looks like this:
Copy-Item -Path $Source -Destination $Destination -Recurse
And the command to invoke Expand-csv looks like this:
Expand-csv Sample.csv Sample.tmplt > Sample.ps1
The output file, Sample.ps1 contains one copy command for each entry in the CSV file
And here is the definition of Expand-csv:
<# This function is a table driven template tool.
It's a refinement of an earlier attempt.
It generates output from a template and
a driver table. The template file contains plain
text and embedded variables. The driver table
(in a csv file) has one column for each variable,
and one row for each expansion to be generated.
5/13/2015
#>
function Expand-csv {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)]
[string] $driver,
[Parameter(Mandatory=$true)]
[string] $template
)
Process
{
$OFS = "`r`n"
$list = Import-Csv $driver
[string]$pattern = Get-Content $template
foreach ($item in $list) {
foreach ($key in $item.psobject.properties) {
Set-variable -name $key.name -value $key.value
}
$ExecutionContext.InvokeCommand.ExpandString($pattern)
}
}
}
My CSV looks like
User,Location
Louis.Smith,CH
I can use a Cmd-Let to show me users from the file
Import-Csv "decommisioned_users.csv"| Where-Object{$_.Location -match "CH"}
I want to move folders to another folder
So in the above example,
We would create a String that looks like
F:\Users\louis.smith
and move that folder to
F:\ArchivedUsers\louis.smith
I can't seem to figure out how to get "louis.smith" from my CSV file (1st column)
Use ForEach-Object. Example:
Import-Csv "decommissioned_users.csv" | Where-Object { $_.Location -eq "CH" } | ForEach-Object {
Move-Object F:\Users\$($_.User) F:\ArchivedUsers\$($_.User) -WhatIf
}
Of course, remove -WhatIf to actually run the command.
I'm attempting to write a script which will read in a CSV generated by querying AD for user information (that part is done) but then will allow me to add a string to the beginning of each value of a column in the CSV file and then export it.
For instance we have this CSV file:
"displayname","Office"
Bob,7142
Janet,8923
SantaClaus,0912
NicCage,0823
I want to take each entry for "Office", add the string "BUG" before it and then export it back out. The modified CSV should look like:
"displayname","Office"
Bob,BUG7142
Janet,BUG8923
SantaClaus,BUG0912
NicCage,BUG0823
At this point, I've been attempting to read in just the "Office" column and then displaying it with "Write-Host". The idea being that if I can do that then maybe I can create a new variable that would be something like:
$BUG = "BUG"
$NewVar = $BUG$Office
Which would hopefully look like the second CSV file. I am extremely new to powershell scripting.
The attempts I've made so far are these:
Attempt #1:
$UserList = Import-CSV C:\Users\username\CSV.csv
$UserList | ForEach-Object ($_.Office) { $UserList }
Attempt #2:
$projectName = import-csv C:\Users\username\CSV.csv | % {$_.Office}
$BUG = "BUG"
$projectName | ForEach-Object ($_) {$projectName}
Attempt #3:
$UserList = Import-CSV C:\Users\username\CSV.csv
#ForEach ($Office in $Userlist) {
#Write-Host $UserList.Office
#}
Attempt #4:
Import-Csv "C:\Users\username\CSV.csv" -Header ("displayname","Office","whenCreated","EmailAddress") | Select-Object Office | Export-CSV -Path C:\users\Username\test.csv
I have gotten it to read out just the Office numbers before using the ForEach-Object loop structure but then it never stops reading out the office numbers so that's unhelpful.
I think I'm going in the right direction, but I just can't figure out how to modify a column like this.
Instead of trying to extract the Office column, just pipe the full data set (all columns) to ForEach-Object, change the value of the Office property and pipe it back to Export-Csv:
$Prefix = "BUG"
Import-Csv .\file.csv | ForEach-Object {
$_.Office = $Prefix + $_.Office
$_
} | Export-Csv .\file_modified.csv -NoTypeInformation