How can I implement a data migration with PowerShell? - powershell

I'm supposed to move data from an old server to a new one while changing the structure.
Example:
old: "C:\test\old\Data\Werkstatt\06. Aufträge\companyA\200031_Signs"
new: "C:\test\new\Data\06. Aufträge\companyA\200031_companyA_Signs"
In the old structure, the orders of a company are in a single folder.
In the new structure, all orders are to be migrated directly under the orders folder. The name consists of the order number + separator + company name + name.
current task is the folders that were successfully copied from "C:\test\old\Data\Werkstatt\06. Aufträge\%company%\" in the folder "C:\test\old\Data\Werkstatt\06. Aufträge\%company%\Z_Transfered" to move.
I tried:
$sourcepath = "C:\test\old\Data\Werkstatt\06. Aufträge"
$basepath = "C:\test\new\Data\06. Aufträge"
$Orders = Get-ChildItem -Path $sourcepath -Directory -Recurse -Depth 1
ForEach ($Order in $Orders ) {
if ($Order.name.StartsWith("20")){
$NewFolderName = "{0}\{1}" -f ($BasePath),($order.Name.insert(6,"_" + $order.parent.Name))
$NewFolder = New-Item -Path $NewFolderName -ItemType "directory"
Copy-Item -Path "$($Order.FullName)\*" -Destination $NewFolder -Recurse -Force
#under construction
$MoveFolderName = Join-Path -path $sourcepath -ChildPath $order.parent | Join-Path -ChildPath "Z_Transfered"
if (-not (Test-Path $MoveFolderName))
{
New-Item -Path $MoveFolderName -ItemType "directory"
}
$MoveFolder = $MoveFolderName +"\" + $order.name
Move-Item -Path "$($Order.FullName)\*" -Destination $MoveFolder
$error > $sourcepath"\error.log"
}
}
I adapted the code I got yesterday. Currently I have one more error in the code.
Copy content to the right place works now.
Currently he creates the folder Z_Transfered below the customer folder. The problem seems to be with Move-Item.
Currently, the folder is not moved to Z_Transfered, only the files under the customer folder are moved and, unfortunately, also renamed. Can someone help me here please?

You can get the parentfolder of a folder by putting .parent to the pathobject > $path.parent. And you can even get the grandparent that way > $path.parent.parent.
So all that is left is a little string manipulation to get the new folder name:
$sourcepath = "d:\test\Data\Orders" # Adjust this
$BasePath = "d:\test\Data\Orders" # Adjust this
$Orders = Get-ChildItem -Path $sourcepath -Directory -Recurse -Depth 2
ForEach ($Order in $Orders ) {
if ( $Order.parent.parent.Name -eq "Orders" ){
$NewFolderName = "{0}\{1}" -f ($BasePath),($order.Name.replace("_","_$($Order.parent)_"))
$NewFolder = New-Item -Path $NewFolderName -ItemType "directory"
Move-Item -Path "$($Order.FullName)\*" -Destination $NewFolder -WhatIf
}
}
In Powershell 5 Get-ChildItem got the -Depth parameter so you can limit it to search only two levels below your $sourcepath. The replace will look for _ in the foldername so make sure thery all contain only one.

it works :)
many thanks for your help.
The script works now as I need it.
$sourcepath = "C:\test\old\Data\Werkstatt\06. Aufträge"
$basepath = "C:\test\new\Data\06. Aufträge"
$Orders = Get-ChildItem -Path $sourcepath -Directory -Recurse -Depth 1
ForEach ($Order in $Orders ) {
if ($Order.name.StartsWith("20")){
$NewFolderName = "{0}\{1}" -f ($BasePath),($order.Name.insert(6,"_" + $order.parent.Name))
$NewFolder = New-Item -Path $NewFolderName -ItemType "directory"
Copy-Item -Path "$($Order.FullName)\*" -Destination $NewFolder -Recurse -Force
$MoveFolderName = Join-Path -path $sourcepath -ChildPath $order.parent | Join-Path -ChildPath "Z_Transfered"
if (-not (Test-Path $MoveFolderName))
{
$MoveFolder = New-Item -Path $MoveFolderName -ItemType "directory"
}
Move-Item -path "$($Order.FullName)\" -Destination $MoveFolderName -force
$error > $sourcepath"\error.log"
}
}

Related

How can I append the creation date to all files in a folder and the subfolders in PowerShell?

I have a small script that can successfully copy all the files from folders and subfolders and append the creation time, but the files in the subfolders do not have the creation time appended to their names.
How can I append the creation date to all files in a folder and the subfolders?
My current script is:
$path = "C:\test1"
$destination = "C:\test2"
Get-ChildItem -path $path | ForEach-Object{
$newname = $_.CreationTime.toString("yyyy-MM-dd") + $_.BaseName +$_.Extension
(Copy-Item -Recurse -Path $_.FullName -Destination ( Join-Path $destination $newname))
}
You were really close, but the -Recurse switch should have been on Get-ChildItem and within the loop you need to make sure the destination subfolder paths exist.
Try
$source = "C:\test1"
$destination = "C:\test2"
Get-ChildItem -Path $source -File -Recurse | ForEach-Object {
# create the new target folderpath for the copy
$targetPath = Join-Path -Path $destination -ChildPath $_.DirectoryName.Substring($source.Length)
# make sure the target path exists, if not create it
$null = New-Item -ItemType Directory -Path $targetPath -Force
# create a new filename with CreationDate prefixed
$newName = '{0:yyy-MM-dd}{1}{2}' -f $_.CreationTime, $_.BaseName, $_.Extension
# copy the file
$_ | Copy-Item -Destination (Join-Path -Path $targetPath -ChildPath $newname) -Force
}
While you could create your own recursive method to copy files and rename them as you go, it would be easier to use Copy-Item recursively and rename the files and folders afterwards:
$Source = "src"
$Destination = "dst"
Copy-Item -Recurse $Source $Destination
foreach ($Item in (Get-ChildItem -Recurse -File $Destination)) {
Rename-Item $Item ($Item.Name + "-" + $Item.CreationTime.toString("yyyy-MM-dd"))
}

Powershell script to create a single folder based of the 5 digits in the name of the pdf's

So far I have tried the following script:
$SourceFolder = "D:\WORK\JetLetter\LKY\LKY_jV_004\"
$TargetFolder = "D:\WORK\JetLetter\LKY\LKY_jV_004\Final\"
Get-ChildItem -Path $SourceFolder -Filter *.pdf |
ForEach-Object {
$ChildPath = Join-Path -Path $_.Name.Replace('.pdf','') -ChildPath $_.Name
[System.IO.FileInfo]$Destination = Join-Path -Path $TargetFolder -ChildPath $ChildPath
if( -not ( Test-Path -Path $Destination.Directory.FullName )){
New-Item -ItemType Directory -Path $Destination.Directory.FullName
}
Copy-Item -Path $_.FullName -Destination $Destination.FullName
}
This creates a folder for every pdf in the folder.
I need it create a single folder based on the 5 digit in the name and move those files into the new folder.
For example: I could have 10 pdf's that have the number "30565" in them and the new folder should be named "30565"
Here are some file names to explain:
LKY_20974_Pr01_1-5000.pdf
to
D:\WORK\JetLetter\LKY\LKY_jV_004\Final\20974
LKY_20974_Pr02_5001-10000.pdf
to
D:\WORK\JetLetter\LKY\LKY_jV_004\Final\20974
LKY_20974_Pr03_10001-15000.pdf
to
D:\WORK\JetLetter\LKY\LKY_jV_004\Final\20974
I have tried to include an else block to the best answer script and haven't had much success. I did however create a separate script that will archive the files before creating a new file. I just have to run it before the main powershell script.
$SourceDir = 'D:\WORK\JetLetter\LKY\LKY_jV_004_9835'
$DestDir = 'D:\WORK\JetLetter\LKY\#Print_Production_Files'
$ArchiveDir = 'D:\WORK\JetLetter\LKY\#Print_Production_Files\#archive'
$Filter = '*.pdf'
$FileList = Get-ChildItem -LiteralPath $SourceDir -Filter $Filter -File
foreach ($FL_Item in $FileList)
{
# this presumes the target dir number is ALWAYS the 2nd item in the split string
$TargetDir = $FL_Item.BaseName.Split('_')[1]
$FullTargetDir = Join-Path -Path $DestDir -ChildPath $TargetDir
if (Test-Path -LiteralPath $FullTargetDir)
{
# the "$Null =" is to suppress unwanted output about what was done
$null = Move-Item -Path $FullTargetDir -Destination $ArchiveDir -Force
}
}
This has made the files and folders a lot more organized.
i think this does what you want done. [grin] the comments seem adequate, but if you have any questions, please ask.
$SourceDir = 'c:\temp\JetLetter\LKY\LKY_jv_004'
$DestDir = 'c:\temp\JetLetter\LKY\LKY_jv_004\Final'
$Filter = '*.pdf'
#region >>> make the dirs and sample files to work with
# remove the entire "#region/#endregion" block when you are ready to work with real data
# make the dirs
$Null = mkdir -Path $SourceDir, $DestDir -ErrorAction 'SilentlyContinue'
# make the test files
$SampleFiles = #(
'LKY_11111_Pr11_1-11111.pdf'
'LKY_22222_Pr22_2-22222.pdf'
'LKY_22222_Pr22_2222-2222.pdf'
'LKY_33333_Pr33_3-3333.pdf'
'LKY_33333_Pr33_33333-33333.pdf'
'LKY_55555_Pr55_5-5555.pdf'
'LKY_77777_Pr77_7-77777.pdf'
'LKY_77777_Pr77_77777-77777.pdf'
'LKY_99999_Pr99_9-99999.pdf'
)
foreach ($SF_Item in $SampleFiles)
{
# the "$Null =" is to suppress unwanted output about what was done
$Null = New-Item -Path $SourceDir -Name $SF_Item -ItemType 'File' -ErrorAction 'SilentlyContinue'
}
#endregion >>> make the dirs and sample files to work with
$FileList = Get-ChildItem -LiteralPath $SourceDir -Filter $Filter -File
foreach ($FL_Item in $FileList)
{
# this presumes the target dir number is ALWAYS the 2nd item in the split string
$TargetDir = $FL_Item.BaseName.Split('_')[1]
$FullTargetDir = Join-Path -Path $DestDir -ChildPath $TargetDir
if (-not (Test-Path -LiteralPath $FullTargetDir))
{
# the "$Null =" is to suppress unwanted output about what was done
$Null = New-Item -Path $FullTargetDir -ItemType 'Directory'
}
$NewFullFileName = Join-Path -Path $FullTargetDir -ChildPath $FL_Item.Name
# leave the file in the source dir if it already is in the final target dir
# you may want to save the not-copied info to a file for later review
if (-not (Test-Path -LiteralPath $NewFullFileName))
{
# the "Move-Item" cmdlet on win7ps5.1 is wildly unreliable
# so i used copy & then remove
$Null = Copy-Item -LiteralPath $FL_Item.FullName -Destination $NewFullFileName
Remove-Item -LiteralPath $FL_Item.FullName
}
else
{
Write-Warning (' {0} already exists in {1}' -f $FL_Item.Name, $FullTargetDir)
Write-Warning ' The file was not moved.'
Write-Warning ''
}
}
screen output only exists for "not moved" files. again, you may want to save the list to a $Var or to a file for later work.
one of the moved files ...
C:\Temp\JetLetter\LKY\LKY_jv_004\Final\22222\LKY_22222_Pr22_2222-2222.pdf

Powershell: Loop through sub-directories and move files

I'm targeting simple task.
I would like to create folder of constant name "jpg" in all subfolders of supplied root folder "D:Temp\IMG" and move all files in every subfolder with extension ".jpg" to that newly created "jpg" folder.
I thought I'll be able to solve this by myself without deep knowledge of powershell, but it seems I have to ask.
So far, I created this code
$Directory = dir D:\Temp\IMG\ | ?{$_.PSISContainer};
foreach ($d in $Directory) {
Write-Host "Working on directory $($d.FullName)..."
Get-ChildItem -Path "$($d.FullName)" -File -Recurse -Filter '*.jpg' |
ForEach-Object {
$Dest = "$($d.DirectoryName)\jpg"
If (!(Test-Path -LiteralPath $Dest))
{New-Item -Path $Dest -ItemType 'Directory' -Force}
Move-Item -Path $_.FullName -Destination $Dest
}
}
What I'm getting out of this is infinite loop of folder "jpg" creation in every subfolder.
Where is my code and logic failing here, please?
The following script would do the job.
$RootFolder = "F:\RootFolder"
$SubFolders = Get-ChildItem -Path $RootFolder -Directory
Foreach($SubFolder in $SubFolders)
{
$jpgPath = "$($SubFolder.FullName)\jpg"
New-Item -Path $jpgPath -ItemType Directory -Force
$jpgFiles = Get-ChildItem -Path $SubFolder.FullName -Filter "*.jpg"
Foreach($jpgFile in $jpgFiles)
{
Move-Item -Path $jpgFile.FullName -Destination "$jpgPath\"
}
}
This will accomplish what you are attempting, I'm pretty sure. Your original script doesn't actually recurse, despite specifying that you want it to (Get-ChildItem has some finicky syntax around that), so I fixed that. Also fixed my suggestion (I forgot that the Extension property includes the preceding dot, so 'FileName.jpg' has '.jpg' as the extension). I added in some checking, and have it throw warnings if the file already exists at the destination.
$Directory = dir D:\Temp\IMG\ -Directory
foreach ($d in $Directory) {
Write-Host "Working on directory $($d.FullName)..."
Get-ChildItem -Path "$($d.fullname)\*" -File -Recurse -filter '*.jpg' |
Where{$_.Directory.Name -ne $_.Extension.TrimStart('.')}|
ForEach-Object {
$Dest = join-path $d.FullName $_.Extension.TrimStart('.')
If (!(Test-Path -LiteralPath $Dest))
{New-Item -Path $Dest -ItemType 'Directory' -Force|Out-Null}
If(Test-Path ($FullDest = Join-Path $Dest $_.Name)){
Write-Warning "Filename conflict moving:`n $($_.FullName)`nTo:`n $FullDest"
}Else{
Move-Item -Path $_.FullName -Destination $Dest -Verbose
}
}
}

Coping files from multiple sub folders using powershell

Copy file from multiple sub-folder to another multiple sub-folder
example :
C:\Nani\Code\Relase4\database1\tables
C:\Nani\Code\Relase1\database1\tables
C:\Nani\Code\Relase2\database1\tables
C:\Nani\Code\Relase3\cycle1\database1\tables
C:\Nani\Code\Relase1\database1.02.tables
I have .sql files in above all folders and i want to copy to
C\Build\database1\tables
if database1\tables directory is not there , i have to create it too ,
$sourceFolder = "C:\Nani\Code"
$targetFolder = "C\Build"
Get-Childitem $sourceFolder -recurse -filter "*.sql" -Exclude $exclude | %{
#If destination folder doesn't exist
if (!(Test-Path $targetFolder -PathType Container)) {
#Create destination folder
New-Item -Path $targetFolder -ItemType Directory -Force
}
Copy-Item -Path $_.FullName -Destination $targetFolder -Recurse -force
}
above code is not creating sub folders in destination ,
I have kept the script very simple for your understanding and commented the sections.
Make sure you add all the validations for paths and error handling. Else if any of the files is giving any issue, then it wont proceed and will break the loop.
Script:
#Keeping all the sources in an array
$Sources = #("C:\Nani\Code\Relase4\database1\tables",
"C:\Nani\Code\Relase1\database1\tables",
"C:\Nani\Code\Relase2\database1\tables",
"C:\Nani\Code\Relase3\cycle1\database1\tables",
"C:\Nani\Code\Relase1\database1.02.tables")
$Destination="C\Build\database1\tables\"
#Iterating each source folder
foreach($source in $sources)
{
#Getting all the sql files under an iteration folder recursively
$files=Get-ChildItem -Path $source -Filter "*.sql" -Recurse
#Iterating all the files underneath a single source folder
foreach ($file in $files)
{
#Copying the files for a single folder to the destination
Copy-Item $file.PSPath -Destination ("$Destination" + ($file.PSParentPath | Split-Path -Leaf) + '_' + $file)
}
}
Hope it helps.
Try this, I am creating each folder first before copying files into it.
$sourceFolder = "C:\Nani\Code"
$targetFolder = "C:\Build"
$sources = Get-Childitem $sourceFolder -recurse -filter "*.sql" -Exclude $exclude | Select FullName, DirectoryName
foreach ($source in $sources)
{
$Releasepath = [regex]::match($source.DirectoryName,'C:\\Nani\\Code\\Release\d').Value
$split = $Releasepath.Replace("\","\\")
$targetfolderLeaf = $source.DirectoryName -split $split | select -Last 1
$targetfolderpath = $targetFolder+$targetfolderLeaf
if (!(Test-Path $targetfolderpath -PathType Container)) {
#Create destination folder
New-Item -Path $targetfolderpath -ItemType Directory -Force
}
Copy-Item -Path $source.FullName -Destination $targetfolderpath -Recurse -force
}

Add multiple folders in one zip file in Powershell

Perhaps my question can be a duplicate, but I'm new in powershell, and cannot figure out, what is wrong with my script, that zipping particular directories:
$path = "C:\backup\DEV82"
if(!(Test-Path -Path $path )){
New-Item -ItemType directory -Path $path
}
cd C:\inetpub\wwwroot\dev82\
$SOURCE = Get-ChildItem * -Directory|Where-Object {$_.FullName -match "App_Config|Resources|bin"}
$dtstamp = (Get-Date).ToString("yyyyMMdd_HHmmss")
Add-Type -assembly "system.io.compression.filesystem"
Foreach ($s in $SOURCE)
{
$DESTINATION = Join-path -path $path -ChildPath "$dtstamp.zip"
If(Test-path $DESTINATION) {
Remove-item $DESTINATION
}
[io.compression.zipfile]::CreateFromDirectory($s.fullname, $DESTINATION)
}
If I execute command in $SOURCE variable, it gathers all required directories, which I want zip http://prntscr.com/j0sqri
$DESTINATION also returns valid value
PS C:\> $DESTINATION
C:\backup\DEV82\20180404_223153.zip
but right now only last folder (Resources) exists in zip file.
Ok, I rewrite my script, using, instead of Zipfile class, Compress-Archive with -Update ( -Update allows to add files\folders into existing archive )
$path = "C:\backup\DEV82"
if(!(Test-Path -Path $path )){
New-Item -ItemType directory -Path $path
}
cd C:\inetpub\wwwroot\dev82\
$SOURCE = Get-ChildItem * -Directory|Where-Object {$_.FullName -match "App_Config|Resources|bin"}
$dtstamp = (Get-Date).ToString("yyyyMMdd_HHmmss")
$DESTINATION = Join-path -path $path -ChildPath "$dtstamp.zip"
Add-Type -assembly "system.io.compression.filesystem"
If(Test-path $DESTINATION) {
Remove-item $DESTINATION
}
Foreach ($s in $SOURCE)
{
Compress-Archive -Path $s.fullname -DestinationPath $DESTINATION -Update
}
$SOURCE is already just a list of folder names, so you don't need the FullName property here:
[io.compression.zipfile]::CreateFromDirectory($s.fullname, $DESTINATION)
Either remove it, or remove the Select-Object from the pipeline here:
$SOURCE = Get-ChildItem * -Directory |
Where-Object {$_.FullName -match "App_Config|Resources|bin"} |
Select-Object -ExpandProperty FullName