Exclude Folder and contents when using Get-ChildItem - powershell

I need some help with a powershell script to exclude certain folders and files.
I have it written so far that it ignores shortcuts and a folder called data, but when the delete command runs, it also deletes all of the content's of the Data folder on the users desktop.
This is the essential part of what I have
$exclude = ('*.lnk', "*data*")
{Get-ChildItem -Path ([environment]::GetFolderPath("Desktop")) -Exclude $exclude -Recurse | Remove-Item -Force -Recurse}
How can I best achieve what I want, this is to have the script run at each startup, remove all desktop content apart from shortcuts and the Data folder+contents. The contents could be anything from exe to mp3 and I do not want to just exclude MP3 from deletion as I may well want them removed from other folders that have been placed on the desktop.
regards

Related

Powershell Script: Search for BATs with specific name and run them

back with another request to try and make my life a little easier. The problem: one of the programs I use deposits BMPs (yes, bitmaps, this is an ancient app, and no, I can't configure it not to make BMPs) where I don't need them. I've got a BAT file that can sweep a folder and remove them, but what I'd really like to do is put a copy of said BAT file in each folder where it leaves them, and then every time I run a backup cycle, have it search for those BAT files, and wherever it finds one, run it. (I'd also need to know how to tell it "look in the same folder you're in"--I think I can do that by something like $searchfolder = "." but please correct me if I'm wrong)
I'm guessing this is a Get-Childitem and ForEach, but I've taken a few stabs at it and it won't work. Does anyone have an idea how to go about it?
This is what I've got so far for the parent script to find all instances of "Clear_BMPs.bat":
Get-ChildItem $sourceDir -Include Clear_BMPs.bat -Recurse | ForEach-Object { call "Clear_BMPs.bat" }
And this is what I've got in the child script, to get rid of the BMPs themselves (the filename for it is "Clear_BMPs.bat":
$searchfile = "*.bmp"
$targetdir = ".\"
Get-ChildItem $targetdir -Include $searchfile | foreach{ "Removing file $($_.FullName)"; Remove-Item -force $_}
I'm still trying to get the Clear_BMPs.bat files to work properly but in my vision it will only search the root of the folder it's in, and not recurse through subdirectories.
Since you're calling from PowerShell, there's no reason to involve batch files, given that the code is under your control.
Indeed, what you show as the content of a Clear_BMPs.bat batch file is PowerShell code, which means you need to store it in a .ps1 file, not a .bat file.
Therefore, your recursive invocation that executes all .ps1 files should look like this:
# Find all 'Clear_BMPs.ps1' scripts in the subdir. tree of $sourceDir
# and invoke them.
Get-ChildItem -Recurse -LiteralPath $sourceDir -Filter Clear_BMPs.ps1 |
ForEach-Object { & $_.FullName }
And the Clear_BMPs.ps1 files in the various directories should contain:
# Remove all *.bmp files from the same dir. in which this .ps1 script is located.
Remove-Item -Path "$PSScriptRoot/*.bmp"
Note the use of the automatic $PSScriptRoot variable, which refers to the directory in which the enclosing .ps1 file is located.

Powershell Cannot create a file when that file already exists when using Move-Item

I'm trying to move png images in subfolders to a subfolder in the folder they are in.
Main folder is called "stuff", images are in variously named subfolders in the "stuff" main folder, and each of these subfolders have a folder name "Oneshot" in them, I'm trying to move these images that are in M:/Stuff/FolderExample/ to M:/Stuff/FolderExample/Oneshot/.
Current code I am using
Get-ChildItem -Path C:\Users\a\Desktop\stuff\*.png -Recurse | Move-Item -Destination "$($_.FullName)\Oneshot\"
How can I make this work? I'm just trying to learn powershell so I can automate this process as I otherwise would need to repeat the process manually for thousands of times
Use a scriptblock ({...}) as the argument to -Destination - this will allow you to access the current pipeline item as $_ during parameter binding:
Get-ChildItem -Path C:\Users\a\Desktop\stuff\*.png -Recurse |Where-Object Directory -notlike *\OneShot | Move-Item -Destination {"$($_.Directory.FullName)\Oneshot\"}
The Where-Object command in the middle of the pipeline will ensure we don't attempt to move pictures already in one of the OneShot folders.
Powershell is not the best idea to move files. The main reason is that you run into problems in case the path becomes too long >256 characters. I would use robocopy for such tasks. It is part of every current windows version.
robocopy M:/Stuff/FolderExample/ M:/Stuff/FolderExample/Oneshot/ /MIR
Please keep in mind that this code will also delete everything that is in M:/Stuff/FolderExample/Oneshot/ and not in M:/Stuff/FolderExample/. So use /MIR with caution.
You could still invoke robocopy in an ps1 file and wrap other powershell code around it e.g. for variables.

Copying group of folders, first in line get's it's contents spilled in the open

I want to copy a group of folders which have various files inside them from one place to a single folder elsewhere. I want to bind said folder group to a variable.
param(
$folders=('../folder1','../folder2')
)
Copy-Item -Path $folders -Destination '../folder3' -Recurse -Force;
This works, however, inside folder3, folder1's contents are spilled out, while folder2's contents are placed in a folder of the same name just like intended.
I need them both to be copied intact, if I switch their places then folder2 gets the same treatment. It's like the script does not read the first folder in line in same way as the others. Am I missing something?
EDIT:
Managed to find a work-around by running additional command to create a folder inside "folder3" named same as first in line folder before copying. Script then places the files inside that folder correctly. Still rather messy, I wonder if it's a bug.
Use a loop
foreach($folder in $folders){
Copy-Item -Path $folder -Destination '../folder3'-Recurse -Force
}

Zipping folders in powershell

Hope fellow scripters can help with this one :) Been breaking my head around the problem for few hours now.
I'm trying to zip up certain folders using powershell.
My folder structure is
Backups
BoxIntranet
Components
Content
Database
Exec
Files
Logs
Multibrowser
Multibrowser\Legacy\Customisation
Packages
ParentPortal
ParentPortal\customisation
StudentPortal
StudentPortal\customisation
Update
WebDav
There are a lot more files and folders in every one of the above but these are the ones I'm mainly interested in.
I am trying to zip it all up using either Write-Zip or Compress-Archive methods in PowerShell but my conditions are.
Only Content, Files, Database folders should be zipped from root
Multibrowser\Legacy\customisation, StudentPortal\Customisation and ParentPortal\customisation folders should also be backed up.
Folder structure should remain the same in the zip file meaning that Root of the zip file should have Content, Files, Database, Multibrowser, ParentPortal and StudentPortal folders. Whilst Content, Files and Database folders should have everything zipped up, Multibrowser, ParentPortal and StudentPortal folders should only have the specified sub directories and all files within them.
Code:
$FilesAndInclude = #("Content", "Files", "Database", "Multibrowser\Legacy\customisation",
"StudentPortal\customisation", "ParentPortal\customisation",
"BoxIntranet\customisation")
$FilesToExclude = #("connectionstrings.config", "inc_dbconn.asp")
Get-ChildItem -Path "C:\Folder" -Include $FilesAndInclude -Recurse -Exclude $FilesToExclude|
Compress-Archive -DestinationPath "Archive.zip"
I've tried the above and it doesn't do anything however if I remove the -Include parameter then it zips up everything however doesn't retain folder structure.
Is there any way to complete what I am after within powershell?
Ok, first things first, the reason that you are having a hard time using the -Include parameter is because it is designed to exclusively include only the things you specify. As such, it will look at the name of things (not their path), and check against the list and if it matches something in the list it will include that item. Since you only list folder names it is only including those folders (but not their contents). So you aren't getting any files passed down the pipe this way. To get around that you'll need to build your file list first, then pipe it to the cmdlet to zip things up.
Next issue is that Compress-Archive doesn't store path info, so you'll need to use Write-Zip. I have included what I think you would want for that cmdlet.
$FilesAndInclude = #("Content", "Files", "Database", "Multibrowser\Legacy\customisation",
"StudentPortal\customisation", "ParentPortal\customisation",
"BoxIntranet\customisation")
$FilesToExclude = #("connectionstrings.config", "inc_dbconn.asp")
[array]$FilesToZip = Get-ChildItem .\* -Exclude $FilesToExclude -File
$FilesToZip += $FilesAndInclude | ForEach{Get-ChildItem .\$_ -Exclude $FilesToExclude -File}
$FilesToZip | Write-Zip -EntryPathRoot $(Resolve-Path .\|Select -Expand Path) -OutputPath Archive.zip

Replace all files in Folder with many sub folders with same name files with powershell

My problem is the following:
I repaired a bunch of dwg that were corrupted and i need to replace the corrupted ones with the repaired ones using power shell. They have the same name, the problem is that i acquired the files through the windows search tool, and i have them all in a single folder.
The original corrupted files exist in many sub folders. How do i copy all files from say folder
"d:\repaired" to "d:\original"
replacing each original files with its repaired one?
I tried doing it with xcopy using the /u, but i also need a way to iterate through the sub-folders.
Ok guys, i did it through command line. I found the answer here:
Replacing a file into multiple folders/subdirectories
I simply used something like this:
Replace C:\SomeFile.Txt C:\SomeRootFolder_ContainsMultipleSubFolders /s
EDIT
$files = Get-ChildItem -path C:\files -Filter *.txt -Recurse
foreach
($file in $files)
{copy-item -path *.txt -destination $files -recurse -force}
Will find all files with a certain extension, then replace them with another file from a directory specified in the -path.