Renaming Specific Files in various folders with Import-Csv - powershell

I’m attempting to rename a bunch of files that are located in multiple folders. The filenames are not unique because they live in multiple directories. Hence, I'd like to fetch all specific files based on their path and then use the Rename-Item cmdlet to make them unique.
I'm using the Import-Csv cmdlet because I have the Paths and New File Names in a text file (headers are oldPath and NewFileName respectively).
I've got this so far:
$documentList = #(Import-Csv -Path 'C:\Users\Desktop\testFolder\fileWithPathAndNewFileName.txt')
$Paths = (ForEach-Object {
(Gci -Path $documentList.oldPath)
})
$Paths | ForEach-Object {Rename-Item -Path $_.FullName -NewName "$($documentlist.newFileName)"}
Unfortunately, this isn't really working, but feels like it's almost there. I think where I'm screwing up is the -NewName parameter. I'm just not sure how to populate the NewFileName object from my text file correctly. Any help would be much appreciated. I apologize in advance if this seems somewhat trivial, I unfortunately haven't been consistent with my Powershell.

Your code is a little confused. ;-) ... if you have CSV file you should name it *.csv.
If I got you right this should be enough actually:
$documentList = Import-Csv -Path 'C:\Users\Desktop\testFolder\fileWithPathAndNewFileName.txt'
foreach ($document in $documentList) {
Rename-Item -Path $document.oldPath -NewName $document.NewFileName
}
You iterate over each row in your CSV file and use the value in the cells as input for the Rename-Item cmdlet. You need to have the complete path including filename to the file in the column "oldPath" and the NewName in the column "NewName"

Related

Powershell - Extract first line from CSV files and export the results

Thanks in advance for the help.
I have a folder with multiple CSV files. I’d like to be able to extract the first line of each of the files and store the results in a separate CSV file. The newly created CSV file will have the first column as the file name and the second column to be the first line of the file.
The output should look something like this (as an exported CSV File):
FileName,FirstLine
FileName1,Col1,Col2,Col3
FileName2,Col1,Col2,Col3
Notes:
There are other files that should be ignored. I’d like the code to loop through all CSV files which match the name pattern. I’m able to locate the files using the below code:
$targetDir ="C:\CSV_Testing\"
Get-ChildItem -Path $targetDir -Recurse -Filter "em*"
I’m also able to read the first line of one file with the below code:
Get-Content C: \CSV_Testing\testing.csv | Select -First 1
I guess I just need someone to help with looping through the files and exporting the results. Is anyone able to assist?
Thanks
You basically need a loop, to enumerate each file, for this you can use ForEach-Object, then to construct the output you need to instantiate new objects, for that [pscustomobject] is the easiest choice, then Export-Csv will convert those objects into CSV.
$targetDir = "C:\CSV_Testing"
Get-ChildItem -Path $targetDir -Recurse -Filter "em*.csv" | ForEach-Object {
[pscustomobject]#{
FileName = $_.Name
FirstLine = $_ | Get-Content -TotalCount 1
}
} | Export-Csv path\to\theResult.csv -NoTypeInformation
I have assumed the files actually have the .Csv extension hence changed your filter to -Filter "em*.csv", if that's not the case you could use the filter as you currently have it.

How with Powershell rename files in folder using text file as input for new names?

Hi everybody and sorry for this lame question , but I´m truly struggling here.
I can put files to be renamed into variable as well as content of the text file, like this:
$filestochange = Get-ChildItem -Path "c:\test"
$FileNames = Get-Content "c:\src.txt"
But how to pass it to Rename-Item command so every line in txt file was used to rename another file in a row?
I tried : Rename-Item -Path $filestochange -NewName $FileNames
Error comes up:
Rename-Item : Cannot convert 'System.Object[]' to the type 'System.String' required by parameter 'Path'. Specified method is not supported.
I was trying ForEach also, but I dont know how to put another variables for the rename-item command it that case as well.
I believe it is very simple, once somebody knows how to use all those $_. {}""
Please, help me go further. ¨Many thanks!
Use a variable to keep track of how many file names you've already used:
$filestochange = Get-ChildItem -Path "c:\test"
$FileNames = Get-Content "c:\src.txt"
# use this variable to keep track of the next file name to use
$counter = 0
foreach($file in $filestochange){
# Remember to check if we have any file names left to use
if($counter -lt $FileNames.Length){
# Rename the next file to the next name in `$FileNames`, then increment counter
$file |Rename-Item -NewName $FileNames[$counter++]
}
else {
Write-Warning "We ran out of file names!"
break
}
}

Use multiple CSVs out a folder individually and save their names

I have a directory with a lot of .csv Files, and have to do a command with each of them. While I have to do that I also need to save each of their names corresponding to on which file the action is taken. (like when the first file fires, I give out all the content of one .csv file into a txt and want the "title" in the .txt to be the filename)?
Also, I don't want this:
Import-Csv -Path (Get-ChildItem -Path C:\PathToFolder\ -Filter '*.csv').FullName
This code would just give me everything in the CSVs as one, but I want to do something with each of them individually.
Process the output of Get-ChildItem in a loop, e.g.
Get-ChildItem -Path C:\PathToFolder -Filter '*.csv' | ForEach-Object {
Import-Csv $_.FullName | ...
}

Bulk PDF Rename - Removing Suffix

I have 1000 PDFs in a folder C:\Users\1003911\Desktop\pdf.
File names are something like 38852ad-Layout1, 38852s-Layout-1, and so on.
I need to remove "-Layout1" from all the PDFs.
I tried few options from this site, but I cannot get it right. Anyone can give me exact code what I should write?
My code is:
Get-ChildItem 'C:\Users\1003911\Desktop\pdf' |
Rename-Item -NewName { $_.Name.Substring(0, $_.Name.Length-12) }
I used this to rename and it worked, but the .pdf extension is removed. How do I retain it?
You got the right idea. I personally think it's easier to use $_.basename and put it in a sub-expression and tack on the .pdf at the end.
Get-ChildItem C:\Users\1003911\Desktop\pdf | rename-item -newname {"$($_.basename.Replace('-layout1','')).pdf"}
also note, I used [string] replace method instead to remove the "-layout1"
Hope this helps :)
Other version of Ricc solution:
Get-ChildItem "C:\Users\1003911\Desktop\pdf" -file -filter "*.pdf" | rename-item -NewName {$_.Name.Replace('-layout1','')}
This version :
Take only file, not directory
Filter on pdf only
Rename Name and not BaseName + concatenation

Copying files defined in a list from network location

I'm trying to teach myself enough powershell or batch programming to figure out to achieve the following (I've had a search and looked through a couple hours of Youtube tutorials but can't quite piece it all together to figure out what I need - I don't get Tokens, for example, but they seem necessary in the For loop). Also, not sure if the below is best achieved by robocopy or xcopy.
Task:
Define a list of files to retrieve in a csv (file name will be listed as a 13 digit number, extension will be UNKNOWN, but will usually be .jpg but might occasionally be .png - could this be achieved with a wildcard?)
list would read something like:
9780761189931
9780761189988
9781579657159
For each line in this text file, do:
Search a network folder and all subfolders
If exact filename is found, copy to an arbitrary target (say a new folder created on desktop)
(Not 100% necessary, but nice to have) Once the For loop has completed, output a list of files copied into a text file in the newly created destination folder
I gather that I'll maybe need to do a couple of things first, like define variables for the source and destination folders? I found the below elsewhere but couldn't quite get my head around it.
set src_folder=O:\2017\By_Month\Covers
set dst_folder=c:\Users\%USERNAME&\Desktop\GetCovers
for /f "tokens=*" %%i in (ISBN.txt) DO (
xcopy /K "%src_folder%\%%i" "%dst_folder%"
)
Thanks in advance!
This solution is in powershell, by the way.
To get all subfiles of a folder, use Get-ChildItem and the pipeline, and you can then compare the name to the insides of your CSV (which you can get using import-CSV, by the way).
Get-ChildItem -path $src_folder -recurse | foreach{$_.fullname}
I'd personally then use a function to edit the name as a string, but I know this probably isn't the best way to do it. Create a function outside of the pipeline, and have it return a modified path in such a way that you can continue the previous line like this:
Get-ChildItem -path $src_folder -recurse | foreach{$_.CopyTo (edit-path $_.fullname)}
Where "edit-directory" is your function that takes in the path, and modifies it to return your destination path. Also, you can alternatively use robocopy or xcopy instead of CopyTo, but Copy-Item is a powershell native and doesn't require much string manipulation (which in my experience, the less, the better).
Edit: Here's a function that could do the trick:
function edit-path{
Param([string] $path)
$modified_path = $dst_folder + "\"
$modified_path = $path.substring($src_folder.length)
return $modified_path
}
Edit: Here's how to integrate the importing from CSV, so that the copy only happens to files that are written in the CSV (which I had left out, oops):
$csv = import-csv $CSV_path
Get-ChildItem -path $src_folder -recurse | where-object{$csv -contains $_.name} | foreach{$_.CopyTo (edit-path $_.fullname)}
Note that you have to put the whole CSV path in the $CSV_path variable, and depending on how the contents of that file are written, you may have to use $_.fullname, or other parameters.
This seems like an average enough problem:
$Arr = Import-CSV -Path $CSVPath
Get-ChildItem -Path $Folder -Recurse |
Where-Object -FilterScript { $Arr -contains $PSItem.Name.Substring(0,($PSItem.Length - 4)) } |
ForEach-Object -Process {
Copy-Item -Destination $env:UserProfile\Desktop
$PSItem.Name | Out-File -FilePath $env:UserProfile\Desktop\Results.txt -Append
}
I'm not great with string manipulation so the string bit is a bit confusing, but here's everything spelled out.