Copy only specific subdirectories and their contents to another directory - windows

In the project directory structure attached below, I am attempting to copy only the subdirectories for January, i.e. Product1_2022-01 and Product2_2022-01, including the files contained within them, to the 2022-01 folder located in the Archive. However, although the subdirectories (and contents) are copied as desired, the February files in the Product1 and Product2 directories one level up, i.e. files fileA-02 and fileB-02, are also copied.
Is it possible to copy only the subdirectories and their contents? I have included the code to reproduce the above scenario. I am new to PowerShell, so any help or advice would be greatly appreciated, thank you.
Directory structure
Code:
$source = #("C:\Product\Testing\Tested\Product1\*",
"C:\Product\Testing\Tested\Product2\*"
)
$destination = "C:\Archive\2022\2022-01"
Copy-Item -Path $source -Destination $destination -Recurse

You're explicitly telling it to copy the entire contents of Product1\*, and Product2\*. If you're looking to narrow it down to just the the subfolders either specify the whole path (Product1\Product1_2022_01), or just part of the path (Product1\Product*):
$source = #("C:\Product\Testing\Tested\Product1\Product*",
"C:\Product\Testing\Tested\Product2\Product*"
)
$destination = "C:\Archive\2022\2022-01"
Copy-Item -Path $source -Destination $destination -Recurse

Related

i need copy command support

Currently I have a directory tree system like the image:
I would like someone to help me create a small piece of code. I want to search all directories, I will see a folder named "C" as above, copy all the data and rename it to a higher level folder, will copy to another folder with the name E . You can only copy the A1 folder and contain the C folder inside. I'm using windows 10. Thank you very much.
In PowerShell, the Copy-Item cmdlet can rename an item while copying. So you want to:
Use Get-ChildItem to find all subfolders of the source named "C".
Pipe these to Copy-Item
Construct the destination path and name using Join-Path.
$Source = 'C:\Source' ### Parent folder of folders "A", "B", etc.
$Dest = 'D:\Dest' ### Destination path for copied folders
# Destination root must exist:
If (!(Test-Path $Dest)) {mkdir $Dest | out-null}
Get-ChildItem -Path $Source -Filter 'C' -Directory -Recurse |
Copy-Item -Destination {Join-Path $Dest $_.Parent.Name} -Recurse
Which can be shortened using positional parameters and aliases to:
gci $Source 'C' -ad -s |
copy -Dest {Join-Path $Dest $_.Parent.Name} -Recurse

Why recursive copying creates wrong folder structure if some parts of path are missing?

I build AWS SDK CPP and copy include files using -Force option. When copying does not find some folders in path, it creates but first time when it creates, some folders are skipped. Here is concreate case. For example ws-cpp-sdk-transfer.
I run command
Copy-Item -Path C:\Dev\aws_sdk_cpp\aws-sdk-cpp\aws-cpp-sdk-transfer\include\* -Destination sdk\include -Recurse -Force
Copied folder content is
c:\Temp\sdk\include\transfer\TransferHandle.h
c:\Temp\sdk\include\transfer\TransferManager.h
c:\Temp\sdk\include\transfer\Transfer_EXPORTS.h
I run same Copy-Item again and now folder content is
c:\Temp\sdk\include\aws\transfer\TransferHandle.h
c:\Temp\sdk\include\aws\transfer\TransferManager.h
c:\Temp\sdk\include\aws\transfer\Transfer_EXPORTS.h
c:\Temp\sdk\include\transfer\TransferHandle.h
c:\Temp\sdk\include\transfer\TransferManager.h
c:\Temp\sdk\include\transfer\Transfer_EXPORTS.h
As you see, subfolder aws is created with correct structure.
If I precreate folder sdk\include\aws first copying works fine.
Why folder structure is not maintained when creating it for the first time?
Edit
Content to be copied
C:\Dev\aws_sdk_cpp\aws-sdk-cpp\aws-cpp-sdk-transfer\include\aws\transfer\TransferHandle.h
C:\Dev\aws_sdk_cpp\aws-sdk-cpp\aws-cpp-sdk-transfer\include\aws\transfer\TransferManager.h
C:\Dev\aws_sdk_cpp\aws-sdk-cpp\aws-cpp-sdk-transfer\include\aws\transfer\Transfer_EXPORTS.h
Copied files when sdk\include\aws exists
c:\Temp\sdk\include\aws\transfer\TransferHandle.h
c:\Temp\sdk\include\aws\transfer\TransferManager.h
c:\Temp\sdk\include\aws\transfer\Transfer_EXPORTS.h
Copied files when sdk does not exists. Please notice: aws is missing.
c:\Temp\sdk\include\transfer\TransferHandle.h
c:\Temp\sdk\include\transfer\TransferManager.h
c:\Temp\sdk\include\transfer\Transfer_EXPORTS.h
When I remove trailing \* from source path, output is always the same and result is as I expected.
Copy-Item -Path C:\Dev\aws_sdk_cpp\aws-sdk-cpp\aws-cpp-sdk-transfer\include -Destination sdk\include -Recurse -Force

How to get nested path of all empty windows directory using cmd

I have a folder and numerous nested folders are present inside that. Many of the folders are empty and I have to copy an empty.property file in those empty folders. So that the end result will be no folder will be completely empty, either it contains another folder, any other file(s) or this empty.property. I have tried to get all the paths using dir /b /s, but it is returning all the paths, not only the empty one. Can anyone help me to get that very efficiently. Thanks.
You can use powershell to do it several ways with one being:
Get-ChildItem -Path C:\Temp -Directory | Where-Object {$_.GetFileSystemInfos().Count -eq 0} |
ForEach-Object -Process { Copy-Item -Path "My\File\to\copy\Path" -Destination $_.FullName }
Basically checks to see which directory doesnt have no files or folders in it, then pipes it to a foreach to a process a Copy-Item request for whatever file/folder you want it to copy from, to the empty folder.

Powershell copying specific files from all subfolders to a single folder

I'm trying to copy all of the cover.jpg files in my music library to one folder. My attempts so far have either landed me with one file in the destination, or every desired file but also in their own folder matching the source (i.e. folders named for each album containing just the cover.jpg file).
Get-ChildItem "C:\Music" -recurse -filter *.jpg | Copy-Item -Destination "C:\Destination"
I realised that the copy-item command was simply overwriting the previous copies thus leaving me with only one file. I then tried going down the renaming route by moving the file then renaming it but of course that failed as the folder I was basing the rename off has now changed. I don't want to change the name of the file before I copy it as other programs still need the cover.jpg to function.
My question is...
Does anybody know how to recursively look through each folder in my music library to find the cover.jpg file, rename it to match the parent folder (or even if possible, grandparent and parent) then copy that file to a new folder making sure to not copy or create any new folders in this destination?
As a bonus, could this check if a file already exists so that if I ran it in the future only new files will be copied?
The file structure for the library is pretty simple. \Music\Artist\Album title\cover.jpg
If you have a music library structure like that, the easiest way would be to use the properties Directory and Parent each FileInfo object returned by Get-ChildItem contains:
$sourcePath = 'C:\Music'
$destination = 'C:\Destination'
# if the destination folder does not already exist, create it
if (!(Test-Path -Path $destination -PathType Container)) {
$null = New-Item -Path $destination -ItemType Directory
}
Get-ChildItem -Path $sourcePath -Filter '*.jpg' -File -Recurse | ForEach-Object {
$newName = '{0}_{1}_{2}' -f $_.Directory.Parent.Name, $_.Directory.Name, $_.Name
$_ | Copy-Item -Destination (Join-Path -Path $destination -ChildPath $newName)
}

Batch file to compress subdirectories individually with Windows native tools

I've seen variations of this question answered, but typically using something like 7zip. I'm trying to find a solution that will work with the capabilities that come with windows absent any additional tools.
I have a directory that contains several hundred subdirectories. I need to individually compress each subdirectory....so I'll wind up with several hundred zip files, one per subdirectory. This is on a machine at work where I don't have administrative privileges to install new software...hence the desire to stay away from 7zip, winRar, etc.
If this has already been answered elsewhere, my apologies...
Never tried that myself, but there is Compress-Archive:
The Compress-Archive cmdlet creates a zipped (or compressed) archive file from one or more specified files or folders. An archive file allows multiple files to be packaged, and optionally compressed, into a single zipped file for easier distribution and storage. An archive file can be compressed by using the compression algorithm specified by the CompressionLevel parameter.
Because Compress-Archive relies upon the Microsoft .NET Framework API System.IO.Compression.ZipArchive to compress files, the maximum file size that you can compress by using Compress-Archive is currently 2 GB. This is a limitation of the underlying API.
Here's a sample script I just hacked together:
# configure as needed
$source = "c:\temp"
$target = "d:\temp\test"
# grab source file names and list them
$files = gci $source -recurse
$files
# target exists?
if( -not (test-path $target)) {
new-item $target -type directory
}
# compress, I am using -force here to overwrite existing files
$files | foreach{
$dest = "$target\" + $_.name + ".zip"
compress-archive $_ $dest -CompressionLevel Optimal -force
}
# list target dir contents
gci $target -recurse
You may have to improve it a bit when it comes to subfolders. In the above version, subfolders are compressed as a whole into a single file. This might not exactly be what you want.
Get-ChildItem c:\path\of\your\folder | ForEach-Object {
$path = $_.FullName
Compress-Archive -Path $path -DestinationPath "$path.zip"
}
I put this, as a quick snippet. Don't hesitate to comment if this does not fit with your request.
In a folder X, there are subfolders Y1, Y2...
Y1.zip, Y2.zip... will be created.
use PowerShell go the the path that you would like to compress, do:
$folderlist = Get-ChildItem "."
foreach ($Folder in $folderlist) { Compress-Archive -path $Folder.Name -destinationPath "$($Folder.Name).zip"}

Resources