Powershell: Exclude numerous folders with -notmatch statement - powershell

I'm creating a small script which will list EXE files on the computer.
$computername = get-content env:computername
get-childitem C: -recurse | ? {$_.fullname -notmatch 'C:\\Windows'} | where {$_.extension -eq ".exe"} | format-table fullname | Out-File "\\server\incomming\$computername.txt"
The problem is that -notmatch doesn't accept more statements. I could copy-paste ? {$_.fullname -notmatch 'C:\\Windows'} and use for other folders like Program Files (x86), Program Files and so on. But I wouldn't like to bloat a script too much.
Is there a way I could exclude numerous folders with -notmatch statement?

You can use the logical operators like -and for more complex logical expressions.
Get-ChildItem C:\ -Recurse | Where-Object { ($_.FullName -notmatch "C:\\Windows") -and ($_.FullName -notmatch "C:\\Program Files") }
For many paths, I'd add them to an array or a hash table before calling Get-ChildItem and use Where-Object check if the pipeline file object path is present in the array or hash table. Eventually, you have to list the paths somewhere, but not necessarily in a single command. For example:
$excludedPaths = #("C:\Windows", "C:\Program Files");
Get-ChildItem C:\ -Recurse | Where-Object { $excludedPaths -notcontains $_.Directory }

Thanks for the answers!
And is it possible to get output longer than it is now?
It is now something like 100 symbols and then it ends with dots if path is longer than that.
I've get something like this -
C:\my files\my programs\prog...

I would use something like this:
get-childitem -literalpath e:\*.exe -Recurse | where { $_.DirectoryName -notmatch "Windows" -and $_.DirectoryName -notmatch "MyOtherFiles"}

Related

Excluding multiple items from Get-ChildItem using Powershell version 4

I'm iterating through a directory tree but trying to filter out a number of things.
This is my cobbled together code;
Get-ChildItem -Path $pathName -recurse -Filter index.aspx* -Exclude */stocklist/* | ? {$_.fullname -NotMatch "\\\s*_"} | Where {$_.FullName -notlike "*\assets\*" -or $_.FullName -notlike ".bk"}
Remove the name index.aspx from the returned item.
I want to filter out any file that starts with and underscore.
Exclude anything that contains /stocklist/ in its path.
Exclude anything that contains /assets/ in its path.
And exclude anything that contains .bk in its path.
This is working for everything but for the .bk in it's path. I'm pretty sure it's a syntax error on my part.
Thanks in advance.
You can create a regex string and use -notmatch on the file's .DirectoryName property in a Where-Object clause to exclude the files you don't need:
$excludes = '/stocklist/', '/assets/', '.bk'
# create a regex of the folders to exclude
# each folder will be Regex Escaped and joined together with the OR symbol '|'
$notThese = ($excludes | ForEach-Object { [Regex]::Escape($_) }) -join '|'
Get-ChildItem -Path $pathName -Filter 'index.aspx*' -File -Recurse |
Where-Object{ $_.DirectoryName -notmatch $notThese -and $_.Name -notmatch '^\s*_' }

Deleting bulk files with the same extension while preserving files with the same extension

Get-ChildItem "I:\TEMP_Dir_SSN\" | %{
if($_.name -ne "fullpath.txt" -or $_.name -ne "SSN_FILES.txt"){
remove-item $_.fullname
}
}
There are two files in the same directory that I don't want to delete. I want to delete all but two .txt files. They need to be preserved in the same directory. However, the rest is garbage and can be removed.
You can utilize Where-Object in your pipeline to accomplish what you're trying to do.
Get-ChildItem "I:\TEMP_Dir_SSN\" |
Where-Object { (($_.Name -notlike 'fullpath.txt') -and
($_.Name -notlike 'SSN_FILES.txt')) } |
Remove-Item
Just a note for more terse reading/writing, you can use the built-in alias GCI and Where
I would use the Exclude parameter to exclude the files:
Get-ChildItem "I:\TEMP_Dir_SSN" -Exclude "fullpath.txt","SSN_FILES.txt" | Remove-Item

Get contents of subfolders containing a string in their name

I want to get all files in subfolders, of the same root folder, that all contain the same string ("foo") in the name of the subfolder(s). Below gives me no error, and no output. I don't know what I'm missing.
Get-ChildItem $rootfolder | where {$_.Attributes -eq 'Directory' -and $_.BaseName -contains 'foo'}) | echo $file
Ultimately, I would like to not just echo their names, but move each file to a target folder.
Thank you.
Here is a solution that includes moving the child files of each folder to a new target folder:
$RootFolder = '.'
$TargetFolder = '.\Test'
Get-ChildItem $RootFolder | Where-Object {$_.PSIsContainer -and $_.BaseName -match 'foo'} |
ForEach-Object { Get-ChildItem $_.FullName |
ForEach-Object { Move-Item $_.FullName $TargetFolder -WhatIf } }
Remove -WhatIf when you are happy it's doing what it should be.
You might need to modify the Get-ChildItem $_.FullName part if you (for example) want to exclude sub-directories of the folders, or if you want to include child items in all subfolders of those paths, but not the folders themselves.
replace
Get-ChildItem $rootfolder | where {$_.Attributes -match 'Directory' -and $_.basename -Match 'foo'}) | echo $file
with
Get-ChildItem $rootfolder | where {($_.Attributes -eq 'Directory') -and ($_.basename -like '*foo*')} | Move-Item $targetPath
your request:
that all contain the same string ("foo")
you have to use the -like comparison operator. Also for exact match I would use -eq (case sensitive version is -ceq) instead of -match since its used for matching substrings and patterns.
workflow:
Gets all the files in directory, sending it through pipe to Where-Object cmdlet where you are filtering based on properties Attributes and Basename. When the filtering is done, its being sent to cmdlet Move-Item.
Adapt the first two vars to your environment.
$rootfolder = 'C:\Test'
$target = 'X:\path\to\whereever'
Get-ChildItem $rootfolder -Filter '*foo*' |
Where {$_.PSiscontainer} |
ForEach-Object {
"Processing folder: {0} " -f $_
Move $_\* -Destination $target
}

PowerShell: List all items except for certain files

Get-childItem | Where-Object { ($_.CreationTime).ToString('dd/MM/yyyy') -EQ 01/01/2017}
How do you create exceptions when listing files ? So if I want to list every file in a directory apart from files called "File 1" and "File 2"
Using the -Exclude parameter on Get-ChildItem:
Get-ChildItem -Exclude File1,File2 | Where-Object { ($_.CreationTime).ToString('dd/MM/yyyy') -EQ 01/01/2017}
Get-childItem | Where-Object {$_.Name -ne 'file 1' -and $_.name -ne 'file 2'}
Either of the above examples will work, it's more of a preference. I personally like to do as much filtering of the data before I pass it along the pipeline.

Compare-Object Delete File if file does not exist on source

I have this PowerShell code that compares 2 directories and removes files if the files no longer exist in the source directory.
For example say I have Folder 1 & Folder 2. I want to compare Folder 1 with Folder 2, If a file doesn't exist anymore in Folder 1 it will remove it from Folder 2.
this code works ok but I have a problem where it also picks up file differences on the date/time. I only want it to pick up a difference if the file doesn't exist anymore in Folder 1.
Compare-Object $source $destination -Property Name -PassThru | Where-Object {$_.SideIndicator -eq "=>"} | % {
if(-not $_.FullName.PSIsContainer) {
UPDATE-LOG "File: $($_.FullName) has been removed from source"
Remove-Item -Path $_.FullName -Force -ErrorAction SilentlyContinue
}
}
Is there an extra Where-Object {$file1 <> $file2} or something like that.?
I am not sure how you are getting the information for $source and $destination I am assuming you are using Get-ChildItem
What i would do to eliminate the issue with date/time would be to not capture it in these variables. For Example:
$source = Get-ChildItem C:\temp\Folder1 -Recurse | select -ExpandProperty FullName
$destination = Get-ChildItem C:\temp\Folder2 -Recurse | select -ExpandProperty FullName
By doing this you only get the FullName Property for each object that is a child item not the date/time.
You would need to change some of the script after doing this for it to still work.
If I am not getting it wrong, the issue is your code is deleting the file with different time-stamp as compared to source:
Did you try -ExcludeProperty?
$source = Get-ChildItem "E:\New folder" -Recurse | select -ExcludeProperty Date
The following script can serve your purpose
$Item1=Get-ChildItem 'SourcePath'
$Item2=Get-ChildItem 'DestinationPath'
$DifferenceItem=Compare-Object $Item1 $Item2
$ItemToBeDeleted=$DifferenceItem | where {$_.SideIndicator -eq "=>" }
foreach ($item in $ItemToBeDeleted)
{
$FullPath=$item.InputObject.FullName
Remove-Item $FullPath -Force
}
Try something like this
In PowerShell V5:
$yourdir1="c:\temp"
$yourdir2="c:\temp2"
$filesnamedir1=(gci $yourdir1 -file).Name
gci $yourdir2 -file | where Name -notin $filesnamedir1| remove-item
In old PowerShell:
$yourdir1="c:\temp"
$yourdir2="c:\temp2"
$filesnamedir1=(gci $yourdir1 | where {$_.psiscontainer -eq $false}).Name
gci $yourdir2 | where {$_.psiscontainer -eq $false -and $_.Name -notin $filesnamedir1} | remove-item
If you want to compare files in multiple dir, use the -recurse option for every gci command.