Powershell 2.0 - Copy file to other location - powershell

How to write powershell script to copy file to other location, including sub folder as well. Example copy fileA from folderA to folderB, in case there are any subfolder within folderB, fileA will copy to that subfolder as well.

Well, you can do it with two commands pretty easily:
# Copy file A to folder B.
Copy-Item -Path $fileA -Destination $folderB
# Get all subdirectories of folder B and copy file A to them.
Get-ChildItem -Path $folderB -Recurse |
? { $_.PSIsContainer } |
% { Copy-Item -Path $fileA -Destination $_.FullName }
It is not immediately obvious to me if it can be done with one command. At least not elegantly.

Related

File System Searches and Files Moves with Powershell

I have a bit of a random task I have created for myself. I basically have a git repo in which there is a file structure and within a specific folder, I have several subfolders and nested in those folders are 3 config folders which have the same name. I am trying to create a powershell script thatll comb through the "Target Folder", copy the "Folder 1", "Folder 2", and "Folder 3", but only copy the contents of the 3 "Config Folder"s, maintaining that file structure, but only copying whats needed. Ideally, after that process, id love to rename these files with part of the name of the folder name to help differentiate. I do have plans to integrate a second part of the script to parse through those config files and export to an excel doc, but not sure how much I need that at the moment. The intended output is below, played around with a few misc file structure commands, but have not found much to help me achieve the below result.
File Structure:
Repo
TARGET FOLDER
DATA
FOLDER1
CONFIGFOLDER
MISC
FOLDER2
CONFIGFOLDER
MISC
FOLDER3
CONFIGFOLDER
ETC
Hoping to end up with
Export Folder
TARGET FOLDER
FOLDER1
CONFIGFOLDER
List of files with "FOLDER1_ogfilename.yaml"
FOLDER2
CONFIGFOLDER
List of files with "FOLDER2_ogfilename.yaml"
FOLDER3
CONFIGFOLDER
List of files with "FOLDER3_ogfilename.yaml"
I have created the following item to attempt this, and it copies the file structure, but it creates a folder for each .yaml file within that folder.
$sourceDir = "C:\Users\hhh\appdev\hhh\data\environments"
$targetDir = "C:\Users\hhh\appdev\targetfolder"
Get-ChildItem $sourceDir -Recurse | % {
$dest = $targetDir + $_.FullName.SubString($sourceDir.Length)
If (!($dest.Contains('research,qa,production,global')) -and !(Test-Path $dest))
{
mkdir $dest
}
Copy-Item $_.FullName -Destination $dest -Force
}
There are issues with your code.
you need to add switch -File to the Get-ChildItem cmdlet to have it look for files, not the directories inside $sourceDir
use Join-Path to construct your destination folder path. By adding the two strings together like you do, you will be missing a backslash
use the files DirectoryName property instead of its FullName when taking the substring from it, otherwise the $dest variable will also include the file name (creating folders for every file)
apparently you wish to not copy files from folders having certain keywords in their path name, so you need to put the copy command inside the test, not below it
Try:
$sourceDir = "C:\Users\hhh\appdev\hhh\data\environments"
$targetDir = "C:\Users\hhh\appdev\targetfolder"
Get-ChildItem $sourceDir -File -Recurse | ForEach-Object {
# use the files DirectoryName, not the FullName property, otherwise the path will include the file name as well
$dest = Join-Path -Path $targetDir -ChildPath $_.DirectoryName.SubString($sourceDir.Length)
# exclude paths containing these words
if ($dest -notmatch 'research|qa|production|global') {
# create the new folder if it does not already exist
$null = New-Item -Path $dest -ItemType Directory -Force
$_ | Copy-Item -Destination $dest -Force
}
}

Copy-Item with overwrite?

Here is a section of code from a larger script. The goal is to recurse through a source directory, then copy all the files it finds into a destination directory, sorted into subdirectories by file extension. It works great the first time I run it. If I run it again, instead of overwriting existing files, it fails with this error on each file that already exists in the destination:
Copy-Item : Cannot overwrite the item with itself
I try, whenever possible, to write scripts that are idempotent but I havn't been able to figure this one out. I would prefer not to add a timestamp to the destination file's name; I'd hate to end up with thirty versions of the exact same file. Is there a way to do this without extra logic to check for a file's existance and delete it if it's already there?
## Parameters for source and destination directories.
$Source = "C:\Temp"
$Destination = "C:\Temp\Sorted"
# Build list of files to sort.
$Files = Get-ChildItem -Path $Source -Recurse | Where-Object { !$_.PSIsContainer }
# Copy the files in the list to destination folder, sorted in subfolders by extension.
foreach ($File in $Files) {
$Extension = $File.Extension.Replace(".","")
$ExtDestDir = "$Destination\$Extension"
# Check to see if the folder exists, if not create it
$Exists = Test-Path $ExtDestDir
if (!$Exists) {
# Create the directory because it doesn't exist
New-Item -Path $ExtDestDir -ItemType "Directory" | Out-Null
}
# Copy the file
Write-Host "Copying $File to $ExtDestDir"
Copy-Item -Path $File.FullName -Destination $ExtDestDir -Force
}
$Source = "C:\Temp"
$Destination = "C:\Temp\Sorted"
You are trying to copy files from a source directory to a sub directory of that source directory. The first time it works because that directory is empty. The second time it doesn't because you are enumerating files of that sub directory too and thus attempt to copy files over themselves.
If you really need to copy the files into a sub directory of the source directory, you have to exclude the destination directory from enumeration like this:
$Files = Get-ChildItem -Path $Source -Directory |
Where-Object { $_.FullName -ne $Destination } |
Get-ChildItem -File -Recurse
Using a second Get-ChildItem call at the beginning, which only enumerates first-level directories, is much faster than filtering the output of the Get-ChildItem -Recurse call, which would needlessly process each file of the destination directory.

Copy files from one folder to many via Powershell

I need to copy the files from one folder to many. Here's an example of my directory structure:
\\files\CA1\Files\Files
CA = state code
1 = office in that state
I want to copy all files from a source folder into the last files folder. The last files folder in that directory structure above is the destination. The script just needs to cycle through all of the directories with that state code and copy the new files into \\files\CA*\files\FILES\ folder. For instance, I want to copy all files from c:\documents into all folders that are for CA, regardless of the office number. Here's what I have so far:
$source = 'C:\Documents'
$destination = (Get-ChildItem -Path \\files\CA*\Files\Files -Recurse -Directory)
foreach ($dir in $destination){
Get-ChildItem $dir.Fullname | ForEach-Object {
$_.FullName
#Copy-Item -Path $Source -Destination $_ -Force -Recurse -WhatIf
}}

Copy and Raname File in Powershell

I want to copy file
base.txt
To Other Folders And I want his name change To The Folder Name.
cd c:\Program\Levels
copy-item *.txt c:\Books -force -recurse
Get-ChildItem C:\Books -Filter *.txt -Recurse | Rename-Item -NewName { $_.Directory.Name}
So he's copying *.txt for the folder 'Books' and renaming the file to 'books.txt' but, he did not copy the file to subfolders within 'Books'
I want it to copy the .txt for subfolders in 'Books' and rename the .txt to the folder name.
Obs: the .txt file is unique
So the file base.txt which is presumably some sort of template will be copied to each subfolder in C:\Books? I think I can understand your logic approach but I offer this as a solution instead.
$templateFile = "C:\temp\base.txt"
Get-ChildItem "C:\Books" | Where-Object {$_.PSIsContainer} |ForEach-Object{
$newName = "{0}\{1}.txt" -f $_.FullName, $_.Name
Copy-Item -Path $templateFile -Destination $newName
}
Gather each subdirectory of "C:\Books" and in each of those directories copy the file base.txt to its new location where its name is the name of the parent folder.

Combine content of several files in folder

I have around 30 directories with .log files in them. I want to go into each folder and combine the text of all the files in the sub-directories separately. I do not want to combine the text of all the files in all the sub-directories.
Example
I have a directory called Machines
in Machines\ I have
Machine2\
Machine3\
Machine4\
Within each Machine* folder, I have :
1.log
2.log
3.log
etc..
I want to create a script that will do:
First: Go into the directory Machine2 and combine the text of all text files in that directory
Second: Go into the Machine3 directory and combine the text of all text file in that directory.
I can use the below if only had one folder, but I need it to loop through several sub folders so I do not have to enter the sub-directory in the command below.
Get-ChildItem -path "W:\Machines\Machine2" -recurse |?{ ! $_.PSIsContainer } |?{($_.name).contains(".log")} | %{ Out-File -filepath c:\machine1.txt -inputobject (get-content $_.fullname) -Append}
I think a recursive solution would work well. Given a directory, grab the content of all *.log files and dump into COMBINED.txt. Then pull the names of all subdirectories, and repeat for each.
function CombineLogs
{
param([string] $startingDir)
dir $startingDir -Filter *.log | Get-Content | Out-File (Join-Path $startingDir COMBINED.txt)
dir $startingDir |?{ $_.PsIsContainer } |%{ CombineLogs $_.FullName }
}
CombineLogs 'c:\logs'