It's my first time using a custom Powershell script and I think I might be missing something. Everything works, except it doesn't copy subfolders and their content.
$sourcePath = 'C:\Users\User\Desktop\test\test1'
$destinationPath = 'C:\Users\User\Desktop\test\test2'
$files = Get-ChildItem -Path $sourcePath -Recurse
$filecount = $files.count
$i=0
Foreach ($file in $files) {
$i++
Write-Progress -activity "Moving files..." -status "($i of $filecount) $file" -percentcomplete (($i/$filecount)*100)
# Determine the absolute path of this object's parent container. This is stored as a different attribute on file and folder objects so we use an if block to cater for both
if ($file.psiscontainer) {$sourcefilecontainer = $file.parent} else {$sourcefilecontainer = $file.directory}
# Calculate the path of the parent folder relative to the source folder
$relativepath = $sourcefilecontainer.fullname.SubString($sourcepath.length)
# Copy the object to the appropriate folder within the destination folder
copy-Item $file.fullname ($destinationPath + $relativepath)
}
i'm sure it's something to do with Path instead of Root or the Recurse option that's not used corretly.
If someone could help me it would be really appreciated.
Thank you!
To copy recursively, use
Copy-Item -Path <src> -Destination <dest> -Recurse
See Official documentation.
This may very well work for you.
As for walking through a previously built list of source files and copying one-by-one as you did, it should work. I did not check/debug the code you put together.
If you actually need this walk through, simply debug your code by printing $files and the source and target of your copy-Item, this will tell you the source of problems. Please post this output in the OP.
You may have to use the option -Directory for Get-ChildItem, or class [System.IO.Path].
Related
Got what I thought was a fairly straightforward question but after several hours of Googling I can't find an answer. Pretty sure Powershell is versatile enough to do this, I'm just not sure how to go code it up.
So basically, I have this:
W:\ (root)
Main Folder 1
Subfolder 1
Sub-Subfolder 1
Sub-Subfolder 2
Sub-Subfolder 3
File1.fil
File2.fil
File3.fil
All I'm trying to do is get Powershell to search Subfolder 1 and move Sub-Subfolders 1-3 (and their contents) into Subfolder 1, but ignore Files 1-3.
The syntax that I've worked up looks like this:
$source = "W:\Main Folder 1\Subfolder 1\"
$destination = "W:\Main Folder\"
Get-ChildItem $source -attributes D -Recurse | Move-Item -Destination "$destination" -Force -Verbose
When I -WhatIf it it looks like it should work, but then when I try it I get the dreaded "cannot create a file when that file already exists" (basically it's saying that it can't create folders in Main Folder 1 with the same names as ones from Subfolder 1). I've got a -Force flag there and I'd have thought this would do the trick, but...here we are.
Any idea what to do to force it to move them? (I don't want it to delete the existing folder to move the new one though.)
If I understand what you're trying to do this code works.
$source = "G:\Test\A\FolderTwo"
$destination = "G:\Test\A"
Get-ChildItem -Path $source -Directory |
Move-Item -Destination $destination -Force -Verbose
Verbose Output:
VERBOSE: Performing the operation "Move Directory" on target "Item: G:\Test\A\FolderTwo\Folder2A Destination: G:\Test\A\Folder2A".
VERBOSE: Performing the operation "Move Directory" on target "Item: G:\Test\A\FolderTwo\Folder2B Destination: G:\Test\A\Folder2B".
The 7 regular files in the Source Folder remained there. The Directories in the Source Folder and all their contents including Sub folders were moved.
Just make sure you have the Source & Destination directories defined correctly.
Note there is no need for the -Recurse switch as moving whole directories also moves their contents.
Edited to remove un-necessary quotes per mklelement0's comment below!
This should get you further. Change the "$($folder.name)-2" to whatever you want to append the new folder names with.
$destination = "W:\Main Folder\"
$source = Get-ChildItem "W:\Main Folder 1\Subfolder 1\" -Directory
foreach ($folder in $source) {
$folder | Move-Item -Destination $destination\"$($folder.name)-2"
}
I know this has been asked a million times, but I can't seem to find anything that works for me. I don't know if there is a permissions issue or what, but I am trying to move files from one server to another using a PowerShell script in the task scheduler and it worked for about a week before it stopped working. There are no errors in the task scheduler, and I'm not well versed in PowerShell at all, I'm just trying to get something quick and simple for our CMS manager to move her files from the website to a folder on another server.
$ORG = "E:\folders\uploads\" ## enter current source folder
$DEST= "\\server-folder-structure\uploads\" ## enter your destination folder
foreach ($ORG in gci $DEST -include *.doc,*.docx,*.pdf,*.png,*.gif,*.jpg,*.jpeg,*.html,*.htm -recurse)
{
Move-Item -path $ORG -destination $DEST ## Move the files to the destination folder
}
I tried this too, in hopes it would work, but still no files are being moved.
Get-ChildItem E:\folder-structure\uploads\* -Include *.doc,*.docx,*.pdf,*.png,*.gif,*.jpg,*.jpeg,*.html,*.htm -Recurse |ForEach-Object { Move-Item $_.FullName \\server-folder-structure\uploads\ }
Am I doing something wrong? Are there permissions to folders that I need to set that I don't know about? Is PowerShell just not the best way to do this? Thanks in advance.
I believe you're making this harder than it should be (with respect to PowerShell being new to you). You don't need a loop on any of your examples if you want to pipe directly to Move-Item:
$ORG = "E:\folders\uploads\" ## enter current source folder
$DEST = "\\server-folder-structure\uploads\" ## enter your destination folder
$filterFor = "*.doc","*.docx","*.pdf","*.png","*.gif","*.jpg","*.jpeg","*.html","*.htm"
Get-ChildItem $ORG -Include $filterFor -File -Recurse |
Move-Item -Destination $DEST -WhatIf
As for what you tried, and as Mathias pointed out, you would be searching your $DEST location in which the files wouldn't exist as they would only be in $ORG; given that that's the actual source folder.
This would also overwrite you $ORG variable with the current item in your iteration in: foreach ($ORG in gci ..){ ... }.
Meaning, your Move-Item would be invalid.
Right in the beginning I should note that I am a bloody beginner because I can't attend it classes in my grade.
I want to create a PowerShell script which will copy everything from
C:\Users\Robert\Desktop\test(lots of folders)
to
C:\Users\Robert\Desktop\neu(lots of folders with the exact same names as above)\price
As an absolute beginner I thought that it will be ok to replace the variable folder name with $_Name because it is the same name in both but I am obviously wrong and don't know why.
Here is my attempt
Copy-Item "C:\Users\Robert\Desktop\test\$_name\*" -Destination "C:\Users\Robert\Desktop\neu\$_Name\price" -Recurse
It is copying something but in one package in a new folder in "neu".
I can't avoid creating this script because it would take me at least two or three days to do it by hand.
I am also sorry for my poor English skills
Thank you
the $_ represents the current pipeline item. i don't see a pipeline in there ... [grin]
the following works by grabbing every file in the source dir & its subdirs, and copying that structure to the destination dir. it uses Splatting to structure the parameters neatly.
$SourceDir = "$env:TEMP\Apps - Copy"
$DestDir = "$env:TEMP\Apps - Copy - Two"
$CI_Params = #{
LiteralPath = $SourceDir
Destination = $DestDir
Force = $True
Recurse = $True
}
Copy-Item #CI_Params
If my understanding is correct:
$src = 'C:\Users\Robert\Desktop\test'
$dst = 'C:\Users\Robert\Desktop\neu\{0}\price'
Get-ChildItem $src -Directory | ForEach-Object {
Copy-Item -Path "$($_.FullName)\*" -Destination ($dst -f $_.BaseName) -Recurse -Force -WhatIf
}
Remove -WhatIf to actually do it.
This has been sort of asked, but none of the questions I've found have quite answered what I'm looking to do. I'm working with PowerShell (brand new to it) to write a script that will search for subdirectories within a directory and move those to a designated directory if found.
My problem lies within the following code:
$Folders = C:\Users\temp
$MoveFolders = Test-Path $Folders -PathType Container
Write-Host $MoveFolders
#I'm writing this with ISE, so I'm using write-host to view output for testing.
The problem I'm running into is that every time this code is ran, it returns true, even when there are no folders within the temp directory. I've tried it with about every conceivable way I can imagine, and tested with get-childitem piped with a where-object, but I want to only execute the move if a subdirectory is present.
The idea behind it is that, if a user somehow adds a file or folder to this specific one, it will be moved when the task scheduler runs the script.
EDIT
Redirecting my question; It always returns true, and a couple of people have pointed out that what I have written will test the temp folder itself; so is there a way to test for any subfolders and store it as a boolean value, which I can then pass to an if statement that will finish the move process?
I believe this is what you want to do.
#get the folders/subfolders from the directory
$folders = Get-ChildItem C:\Users\temp -Recurse -Directory
#loop through the folders
foreach($folder in $folders) {
#copy the the folder(s) and item(s) within to the destination
Copy-Item -Path $folder.FullName -Destination C:\test -Recurse
}
Here is the updated answer since you edited your question.
$items = Get-ChildItem -Path C:\Users\mkrouse\Desktop\test -Directory -Recurse
#if items is equal to null, then there are no subfolders so assign the boolean to true
if($items -eq $null) {
[bool]$NoSubfolders = $true;
} else {
[bool] $NoSubfolders = $false;
}
Your code tests whether "c:\users\temp" is a folder - which is always true. You need to look for folders within "c:\users\temp". One approach:
$Folders = "C:\temp"
$MoveFolders = Get-ChildItem -Path $folders -Directory
Write-Host $MoveFolders.Count
$MoveFolders now contains a list of all folders within "c:\users\temp". Now you have a list of folders to be moved.
We have a script running daily that removes old files and directories from an area that people use to transfer data around. Everything works great except for one little section. I want to delete a folder if it's older than 7 days and it's empty. The script always shows 1 file in the folder because of the thumbs.db file. I guess I could check to see if the one file is thumb.db and if so just delete the folder but I'm sure there is a better way.
$location = Get-ChildItem \\dropzone -exclude thumbs.db
foreach ($item in $location) {
other stuff here going deeper into the tree...
if(($item.GetFiles().Count -eq 0) -and ($item.GetDirectories().Count -eq 0)) {
This is where I delete the folder but because the folder always has
the Thumbs.db system file we never get here
}
}
$NumberOfFiles = (gci -Force $dir | ?{$_ -notmatch "thumbs.db"}).count
You can try the get-childitem -exclude option where all files/items in your directory will be
counted except those that end in db:
$location = get-childitem -exclude *.db
It also works out if you specify the file to exclude, in this case thumbs.db
$location = get-childitem -exclude thumb.db
Let me know if this works out.
Ah, I also just noticed something,
$location = get-childitem -exclude *.db
Will only handle .db items in the location directory, if you're going deeper into the tree (say from your GetFiles() and GetDirectories() methods) then you may still find a thumb.db. Hence you'll have to add the exclude option in these methods to ignore thumbs.db.
So, for example in your $item.getFiles() method, if you use get-childitem you will have to specify the -exclude option as well.
Sorry, I should have read your question more closely.
Use this method to provide a exclusion list in the form of a simple text file to exclude specific files or extensions from your count:
$dir = 'C:\YourDirectory'
#Type one filename.ext or *.ext per line in this txt file
$exclude = Get-Content "C:\Somefolder\exclude.txt"
$count = (dir $dir -Exclude $exclude).count
$count