PowerShell--Finding any and all Subdirectories and Moving them - powershell

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.

Related

PowerShell script does not copy subfolders and their content

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].

PowerShell Remove-Item exclude folder files

I have a simple script which is used to delete files from a folder. The script accepts two parameters:
The path of the folder to delete from
A list of items to be excluded from deletion
This is the script I have:
Param(
[Parameter(Mandatory=$True)]
[string]$pathDeleteFrom,
[Parameter(Mandatory=$True)]
[string[]]$excludeFiles
)
Remove-Item -path $pathDeleteFrom -exclude $excludeFiles -Recurse
I'm testing the script in a folder with the following structure:
Example (running the script for path "C:/test/files/*"):
If "*.txt" is excluded, only the .json files are removed.
If I want to delete all files except the folder and it's contents I tried excluding "folder" and "folder/*", however it doesn't seem to work.
What I'm failing to understand is, whether there's a way for me to exclude the "folder" and it's contents using wildcards.
I know that this is probably a simple question but I have tried searching online but failed to find an example similar to the scenario that I have.
This should do what you're trying to accomplish... just fill in the blank and modify the condition statements to what you need.
$items = Get-ChildItem -Path "Directory Path" -Recurse
foreach($item in $items)
{
if($item.name -like "*.TXT" -or $item.name -like "*.Json")
{
#CODE HERE
}
elseif(($item.GetType()).Name-eq "DirectoryInfo" -and $item.name -eq "Directory Name")
{
#CODE HERE
}
}

Excluding Parent Directory if Any File is New

My company has individual folders on a share for each project they are working on, and if no files inside one of those folders or its subfolders has been touched in the last six months, I want to move them to an archive location. If any one file within the folder or any of its subfolders have been modified in the last six months, I want to skip the entire parent directory. I'm most of the way there now, but my current iteration only skips the individual files, and I'm not sure how to specify skipping the entire parent. Here is my current script:
$Date = (Get-Date).AddMonths(-6)
$Source = 'C:\Scripts\Source'
$Dest = 'C:\Scripts\Test Target'
Get-ChildItem $Source -File -Recurse | Where {$_.LastWriteTime -lt $Date} | ForEach {
$actualSource = Split-Path $_.FullName
$actualDest = Split-Path $_.FullName.Replace($source,$dest)
robocopy $actualSource $actualDest $_.Name /SEC
}
When using my test directories, I have a folder C:\Scripts\Source\Drivers. The script copies that Drivers folder like I want it to, but if I put a newer file anywhere within that Drivers folder, I want the entire folder to be skipped. Currently, the folder and anything older than six months within the folder are still being copied, and it is just skipping the individual files which are newer.
Please let me know if any more information is needed.
Simply pull back your copy and recurse statement one level up. First you want to iterate through all the parent folders. Then for each parent folder, recurse and check to see if there is any modified files, if there is, then copy the folder:
$Date = (Get-Date).AddMonths(-6)
$Source = 'C:\Scripts\Source'
$Dest = 'C:\Scripts\Test Target'
$ParentFolders = Get-ChildItem $Source -Directory
Foreach($Folder in $ParentFolders){
$NewFiles = Get-ChildItem $Folder -File -Recurse | Where {$_.LastWriteTime -lt $Date}
if($NewFiles.Count -eq 0)
{
#Archive
robocopy $Folder $Dest /SEC
}
}

PowerShell script isn't copying like I want

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.

Powershell getfiles.count() to exclude thumbs.db

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