Moving files in powershell into different location - powershell

It's supposed to move all files in $source into $destination. But something is not working here..
$source = Get-ChildItem 'E:\files' -Recurse
$destination = Get-ChildItem "C:\destination" -Recurse
foreach($file in $source)
{
Move-Item -Path $source -Destination $destination
}

This is how you are supposed to do it:
$source = Get-ChildItem -Path X:\Directory -Recurse
$destination = "Y:\Directory"
foreach ($item in $source) { Move-Item -Path $item -Destination $destination }
A one-liner would be:
Get-ChildItem -Path X:\Directory -Recurse | Move-Item -Destination Y:\Destination
Your first mistake was the declaration of the destination variable: It should be just $destination = "C:\Destination"; and, second, you created an "index" named $file but you did not use it inside the foreach, which should be Move-Item -Path $file -Destination $destination.

Related

is file a child of given folder in PS? [duplicate]

Trying to get my copy-item to copy everything in directory except a subfolder. I was able to exclude in the folder and files, but not subfolders.
I tried using get-children and the -exclude in the copy-item but didn't exclude them as I hope
$exclude = "folder\common"
Get-ChildItem "c:\test" -Directory |
Where-Object{$_.Name -notin $exclude} |
Copy-Item -Destination 'C:\backup' -Recurse -Force
Hoping that the common folder will exist but nothing in it would be copy.
Thanks for the help
I think this should do what you need:
$sourceFolder = 'C:\test'
$destination = 'C:\backup'
$exclude = #("folder\common") # add more folders to exclude if you like
# create a regex of the folders to exclude
# each folder will be Regex Escaped and joined together with the OR symbol '|'
$notThese = ($exclude | ForEach-Object { [Regex]::Escape($_) }) -join '|'
Get-ChildItem -Path $sourceFolder -Recurse -File |
Where-Object{ $_.DirectoryName -notmatch $notThese } |
ForEach-Object {
$target = Join-Path -Path $destination -ChildPath $_.DirectoryName.Substring($sourceFolder.Length)
if (!(Test-Path -Path $target -PathType Container)) {
New-Item -Path $target -ItemType Directory | Out-Null
}
$_ | Copy-Item -Destination $target -Force
}
Hope that helps
I think using the -exclude parameter on Get-ChildItem would work:
$exclude = 'Exclude this folder','Exclude this folder 2','Folder3'
Get-ChildItem -Path "Get these folders" -Exclude $exclude | Copy-Item -Destination "Send folders here"
Here is an example:
$exclude= 'subfolderA'
$path = 'c:\test'
$fileslist = gci $path -Recurse
foreach ($i in 0..$fileslist){ if( -not ($i.Fullname -like "*$($exlusion)*")){ copy-item -path $i.fullname -Destination 'C:\backup' -Force } }

Trying to use powershell to put files in folders based on their extension and the name of the folder

I have a directory with three files: .xlsx, .docx, and .txt, I also have folders in that same directory called xlsx, docx and txt. Basically trying to put each file into its corresponding folder, as a way to practice my PowerShell skills. I'm very new to PowerShell and have tried the following. I can tell its wrong, but I'm not quite sure why.
$folders = Get-ChildItem -Directory
$files = Get-ChildItem -File
foreach ($file in $files) {
foreach ($folder in $folders) {
if ("*$file.extension*" -like "*$folder.Name*") {
move-item $file -Destination "C:\Users\userA\Desktop\$folder.name"
}
}
}
Try the code below. With the Where-Object function, you find the corresponding file. I remove the dot because it is included in the extension otherwise.
$folders = Get-ChildItem -Directory
$files = Get-ChildItem -File
foreach ($file in $files) {
$folder = $folders | Where-Object { $_.Name -Like $file.Extension.Replace(".","") }
Move-Item -Path $file -Destination $folder
}
In your example, be careful how your strings are actually been interpreted. If you have "*$item.Name*" the string actually "* variable.Name*". In this case you need to use "*$($var.Name)*" in order to get the correct string.
Here are some adjustments to your approach that make it work. Breaking the -Destination parameter out to a separate variable $newpath lets you set a debug statement there so you can easily examine what it's creating.
$folders = Get-ChildItem -Directory
$files = Get-ChildItem -File
foreach ($file in $files) {
foreach ($folder in $folders) {
if ($file.extension.trim(".") -like $folder.Name) {
$newpath = ("{0}\{1}" -f $folder.FullName, $file.Name)
move-item $file -Destination $newpath
}
}
}
You could even create target folders for extensions if they do not exist yet:
$SourceFolder = C:\sample
$TargetFolder = D:\sample
Get-ChildItem -Path $SourceFolder -File |
ForEach-Object{
$DesinationFolder = Join-Path -Path $TargetFolder -ChildPath $_.Extension.TrimStart('.')
if(-not (Test-Path -Path $DesinationFolder)){
New-Item -Path $DesinationFolder -ItemType Directory | Out-Null
}
Copy-Item -Path $_.FullName -Destination $DesinationFolder -Force
}

Powershell copy only selected files with folder structure

I have a folder hierarchy with a lot of files.
I need to copy all folders and only selected files. For this purposes I write script:
$path = "D:\Drop\SOA-ConfigurationManagement - Test\181"
$files = Get-ChildItem -Path $path -Recurse | ? { $_.Name -like "system.serviceModel.client.config" }
$Destination = "D:\test\"
Copy-Item $files -Destination $Destination -recurse
When I execute variable $files, it returns correct path:
But when I execute Copy-Item it returns not full path:
Perhaps my approach is wrong. If so, how to copy entire folder structure, and only selected files (in this case system.serviceModel.client.config file)?
UPD1 Ok, I've found, how to copy only folders:
$path = "D:\Drop\SOA-ConfigurationManagement - Test\181\"
$Destination = "D:\test\"
Copy-Item $path $Destination -Filter {PSIsContainer} -Recurse -Force
But how to copy only selected files, preserving their location? What needs to be in $Destination variable?
$files = Get-ChildItem -Path $path -Recurse | ? { $_.Name -like "system.serviceModel.client.config" } | % { Copy-Item -Path $_.FullName -Destination $Destination }
This code would keep the directory structure the same too
$path = "D:\Drop\SOA-ConfigurationManagement - Test\181\"
$Destination = "D:\test\"
$fileName = "system.serviceModel.client.config"
Get-ChildItem -Path $path -Recurse | ForEach-Object {
if($_.Name -like $fileName) {
$dest = "$Destination$(($_.FullName).Replace($path,''))"
$null = New-Item $dest -Force
Copy-Item -Path $_.FullName -Destination $dest -Force
}
}
To copy the whole folder structure AND files with a certain name, below code should do what you want:
$Source = 'D:\Drop\SOA-ConfigurationManagement - Test\181'
$Destination = 'D:\test'
$FileToCopy = 'system.serviceModel.client.config'
# loop through the source folder recursively and return both files and folders
Get-ChildItem -Path $Source -Recurse | ForEach-Object {
if ($_.PSIsContainer) {
# if it's a folder, create the new path from the FullName property
$targetFolder = Join-Path -Path $Destination -ChildPath $_.FullName.Substring($Source.Length)
$copyFile = $false
}
else {
# if it's a file, create the new path from the DirectoryName property
$targetFolder = Join-Path -Path $Destination -ChildPath $_.DirectoryName.Substring($Source.Length)
# should we copy this file? ($true or $false)
$copyFile = ($_.Name -like "*$FileToCopy*")
}
# create the target folder if this does not exist
if (!(Test-Path -Path $targetFolder -PathType Container)) {
$null = New-Item -Path $targetFolder -ItemType Directory
}
if ($copyFile) {
$_ | Copy-Item -Destination $targetFolder -Force
}
}
try this
$path = 'D:\Drop\SOA-ConfigurationManagement - Test\181\'
$Destination = 'D:\test\'
$files = Get-ChildItem -Path $path -Recurse -File | where Name -like "*system.serviceModel.client.config*" | %{
$Dir=$_.DirectoryName.Replace($path, $Destination)
$NewPAthFile=$_.FullName.Replace($path, $Destination)
#create dir if not exists
New-Item -Path $Dir -ItemType Directory -Force -ErrorAction SilentlyContinue
#copy file in new dir
Copy-Item $_.FullName $NewPAthFile
}
With minimal changes I'd suggest the following:
$path = "D:\Drop\SOA-ConfigurationManagement - Test\181"
$files = Get-ChildItem -Path $path -Recurse | ? { $_.Name -like "system.serviceModel.client.config" }
$Destination = "D:\test\"
$files | % { $_ | Copy-Item -Destination $Destination -recurse }
You can even put the whole copy on one line:
$path = "D:\Drop\SOA-ConfigurationManagement - Test\181"
$Destination = "D:\test\"
Get-ChildItem -Path $path -Recurse | ? { $_.Name -like "system.serviceModel.client.config" } | % { $_ | Copy-Item -Destination $Destination -recurse }
Copy-Item can find the path from the stream of input objects but it doesn't seem to be able to take a collection of System.IO.FileInfo objects as an argument to Path.

Copy-item exclude Sub-folders

Trying to get my copy-item to copy everything in directory except a subfolder. I was able to exclude in the folder and files, but not subfolders.
I tried using get-children and the -exclude in the copy-item but didn't exclude them as I hope
$exclude = "folder\common"
Get-ChildItem "c:\test" -Directory |
Where-Object{$_.Name -notin $exclude} |
Copy-Item -Destination 'C:\backup' -Recurse -Force
Hoping that the common folder will exist but nothing in it would be copy.
Thanks for the help
I think this should do what you need:
$sourceFolder = 'C:\test'
$destination = 'C:\backup'
$exclude = #("folder\common") # add more folders to exclude if you like
# create a regex of the folders to exclude
# each folder will be Regex Escaped and joined together with the OR symbol '|'
$notThese = ($exclude | ForEach-Object { [Regex]::Escape($_) }) -join '|'
Get-ChildItem -Path $sourceFolder -Recurse -File |
Where-Object{ $_.DirectoryName -notmatch $notThese } |
ForEach-Object {
$target = Join-Path -Path $destination -ChildPath $_.DirectoryName.Substring($sourceFolder.Length)
if (!(Test-Path -Path $target -PathType Container)) {
New-Item -Path $target -ItemType Directory | Out-Null
}
$_ | Copy-Item -Destination $target -Force
}
Hope that helps
I think using the -exclude parameter on Get-ChildItem would work:
$exclude = 'Exclude this folder','Exclude this folder 2','Folder3'
Get-ChildItem -Path "Get these folders" -Exclude $exclude | Copy-Item -Destination "Send folders here"
Here is an example:
$exclude= 'subfolderA'
$path = 'c:\test'
$fileslist = gci $path -Recurse
foreach ($i in 0..$fileslist){ if( -not ($i.Fullname -like "*$($exlusion)*")){ copy-item -path $i.fullname -Destination 'C:\backup' -Force } }

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
}
}
}