Identify Empty Folders - powershell

I would like to identify a specific empty folder in our user profiles.
I have a text file containing all of our user names that I want the script to refer to. The script will loop each user directory and either output to file or screen and say if the directory is empty. Hidden files do not have to count!
Something similar
FOR /F %U IN (C:\UserList\UserList.TXT) DO *Find and List Empty Folder* \\Server\Share\%U\Target_Folder
Powershell solutions welcome!

This article on Technet provides the following Powershell code snippet to identify all empty folders:
$a = Get-ChildItem C:\Scripts -recurse | Where-Object {$_.PSIsContainer -eq $True}
$a | Where-Object {$_.GetFiles().Count -eq 0} | Select-Object FullName
Replace "C:\Scripts" with the root folder you want to search.
Update:
The following script will get you in the ballpark.
$content = Get-Content C:\Temp\FolderList.txt
foreach ($line in $content)
{
Write-Host $line -NoNewline
$testObject = Test-Path -Path $line
if ($testObject)
{
$folder = Get-Item -Path $line
$filesCount = $folder.GetFiles().Count
if ($filesCount.Equals(0))
{
Write-Host " - Empty folder"
}
else
{
Write-Host " - Contains files"
}
}
else
{
Write-Host " - Invalid path"
}
}

Related

Get missing file name in a sequence of files

In a folder i have many files, they are sequential, type ABC001.csv,ABC002.csv,ABC003.csv and so on. Sometimes this sequence breaks, then there are missing files and I need to identify which of the sequence are missing in the folder manually, we have more than 700files.
Does anyone here know a power shell script to help me with this task?
If all files to be counted always have a naming format ABC<3-digit number>.csv, then you could do this:
# get an array of integer sequence numbers from the files
$sequence = (Get-ChildItem -Path 'D:\Test' -Filter 'ABC*.csv' -File).BaseName |
Where-Object { $_ -match '(\d{3})$' } | ForEach-Object { [int]$matches[1] } |
Sort-Object -Unique
# get the missing numbers (if any) and output filenames to be collected in $missingFiles
$missingFiles = Compare-Object $sequence (1..($sequence[-1])) -PassThru | ForEach-Object {
'ABC{0:D3}.csv' -f $_ # reconstruct the filename with the missing number
}
# output on screen
if (#($missingFiles).Count) {
Write-Host "Files missing:" -ForegroundColor Yellow
$missingFiles
}
else {
Write-Host "All files are in sequence" -ForegroundColor Green
}
Of course, change the rootpath of the files (here 'D:\Test') to your own
In this example,
The script is located in the same location as a folder named "Temp".
The "Temp" folder had files ABC001.csv through ABC717.csv.
Files ABC123.csv and ABC555.csv were deleted from "Temp" folder.
for ($i = 1; $i -lt 718; $i++) {
$FileName = $PSScriptRoot + '\Temp\ABC{0:d3}.csv' -f $i
if(-not (Test-Path -Path $FileName -PathType Leaf)) {
Write-Host "Missing $FileName"
}
}
Output when ran:
Missing 123
Missing 555

Create a Clickable Folder Link in Powershell

I have a script that searches for a file name in a folder and gives a folder path. Does Powershell have a way to make these folder paths a clickable link? I want to bring up a list of file directory paths that I can click on.
Here is what the code looks like.
#Declare Variables.
$Software = #()
#Delcares Directories to search.
$Directories = #(
'\\Software\Unlicensed Software'
'\\Software\Licensed Software')
#Gets folder contents of directories at a depth of three.
Foreach($Directory in $Directories)
{
$Path = Get-ChildItem $Directory -Recurse -Depth 3| ?{ $_.PSIsContainer } | Select-Object FullName;
$Software += $Path
}
#Gets user string.
$target = Read-Host -Prompt 'Input a software name or part of a name. ("Exit" to quit)';
#Finds matches and adds them to Links.
while ($target -ne "exit")
{
$count = 0;
$Links = New-Object Collections.Generic.List[string];
Foreach ($line in $Software)
{
if($line -like "*$target*")
{
$Links.Add($line.FullName);
$count += 1;
}
#Stops code when results are greater than 100 entries.
if($count -gt 99)
{
Write-Output "Your search result yielded more than 100 entries. Try narrowing down your search."
Break
}
}
#Prints links.
ForEach($Link in $Links)
{
Write-Output $Link;
}
Write-Host `n$count" entries found`n";
#Asks users if they would like to continue.
$target = Read-Host -Prompt 'Input a software name or part of a name ("Exit" to quit)';
}
#Exits Program
Write-Host "Press any key to continue ...";
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown");
This is a quite simple way you could use to select a folder an open it, it will display an Out-GridView until you cancel or close the grid and open the folder once you make a selection. If you're looking for something better looking and more complex you would have to code your own WinForm app.
$directories = Get-ChildItem $env:USERPROFILE -Directory |
Select-Object Name, FullName
do
{
$selection = $directories |
Out-GridView -PassThru -Title 'Choose a Folder'
if($selection){ Invoke-Item $selection.FullName }
} while($selection)
You could make a HTML File:
Add-Type -AssemblyName System.Web
[System.Web.HttpUtility]::HtmlDecode((gci | select Name,#{n='Fullpath'; e={(("<a href='file://" +$_.fullname+"'>"+$_.Fullname+'</a>' ))}} | ConvertTo-Html)) | out-file c:\file.html
iex c:\file.html

powershell check for existence of multiple inputs

I need to check if files from input exists.
I split multiple inputs for example BWMDL.VML BWMDL.STA etc and write out files that are already in folder
I check if files from input are present in folder or not.
But I'm getting True, even if the file doesnt exists, also the output from test-path is printed twice, with different result.
Set-Variable -Name Files -Value (Read-Host "instert file name")
Set-Variable -Name FromPath -Value ("C:\Users\Desktop\AP\AP\parser\*.VML" , "C:\Users\Desktop\AP\AP\parser\*.STA")
Set-Variable -Name NameOfFiles (Get-ChildItem -Path $FromPath "-Include *.VML, *.STA" -Name)
Write-Host "FILES IN FOLDER:"
$NameOfFiles
Write-host "---------------------"
Write-host "FILES FROM INPUT: "
Splitted
Write-host "---------------------"
Write-host "FILE EXISTS: "
ForEach ($i in Splitted) {
FileToCheck
}
function Splitted {
$Files -Split " "
}
function FileToCheck {
Test-Path $FromPath -Filter $Files -PathType Leaf
}
For example I'm getting like this result
You are over complicating this.
Once you get the names of all files with extension .VML or .STA in an array, you do not have to use Test-Path anymore, since you know the files in array $NameOfFiles actually do exist, otherwise Get-ChildItem would not have listed them.
This means you can get rid of the helper functions you have defined, which BTW should have been written on top of your code, so before calling on them.
Try
$Files = (Read-Host "instert file name(s) separated by space characters" ) -split '\s+'
$FromPath = 'C:\Users\Desktop\AP\AP\parser'
# if you need to recurse through possible subfolders
$NameOfFiles = (Get-ChildItem -Path $FromPath -Include '*.VML', '*.STA' -File -Recurse).Name
# without recursion (so if files are directly in the FromPath):
# $NameOfFiles = (Get-ChildItem -Path $FromPath -File | Where-Object {$_.Extension -match '\.(VML|STA)'}).Name
Write-Host "FILES IN FOLDER:"
$NameOfFiles
Write-host "---------------------"
Write-host "FILES FROM INPUT: "
$Files
Write-host "---------------------"
Write-host "FILE EXISTS: "
foreach ($file in $Files) { ($NameOfFiles -contains $file) }
Output should look like
instert file name(s) separated by space characters: BWMDL.VML BWMDL.STA
FILES IN FOLDER:
BWMDL.STA
BWMDL.VML
---------------------
FILES FROM INPUT:
BWMDL.VML
BWMDL.STA
---------------------
FILE EXISTS:
True
True

Test-Path returning true on empty folders

Test-Path is returning true, or at least appears to be on folders that are empty if they are located in the same directory as folders returning true that are NOT empty.
I've tried adjusting wildcard locations, adding additional \ to change paths to see if I could reduce the number of returned folders, but I cannot. I assumed the foreach portion and Test-Path would individually check each folder and return a result, but it appears once it sees contents, all folders thereafter are returned as true.
[int]$subDay = Read-Host "Enter days to subtract"
$date0 = (Get-Date).AddDays(-$subDay).ToString("yy") +
((Get-Date).AddDays(-$subDay).DayOfYear).ToString("D3")
$date1 = (Get-Date).AddDays(-$subDay).ToString("yyyy") +
((Get-Date).AddDays(-$subDay).DayOfYear).ToString()
$path0 = ".\11"
$path1 = ".\12"
$path2 = ".\13"
$a = $path0, $path1, $path2
function Split {
Param ($split)
Split-Path -Parent $split |
Get-Item |
Select-Object -ExpandProperty Name |
Add-Content $archLog
foreach ($element in $a) {
if (Test-Path $element\$date1\"$date0*"\*) {
Split $element\$date1
Split $element\$date1\"$date0*"\*
} else {
Split $element\$date1
Write-Output "Folders do not exist or are empty." |
Add-Content $archlog
}
}
I expected the code to return folder name if it had contents, which it does. However, if an empty folder exists where a folder with contents does, both are returned. If you take away the contents of the folder, none are returned.
To be able to see every subfolder that contains a file use the parameters -file and -recurse of the Get-ChildItem cmdlet:
$a = $path0, $path1, $path2
foreach ($element in $a) { Get-ChildItem -Path $element\$date1 -file -Recurse | foreach {$_.Directory.Name} | select -uniq }

using a global variable in multiple functions powershell

I have this code :
$Count=0
Function DryRun-UploadFile($DestinationFolder, $File, $FileSource, $Count)
{
if($FileSource -eq $null){
$FileSource = $Folder
}
$path= [String]$FileSource+'\'+$File
$Size = get-item $Path
$Size = $Size.length
if($Size -lt 160000){
Write-Host "Passed"
}else{
$Count=$Count+1
}
}
function DryRun-PopulateFolder($ListRootFolder, $FolderRelativePath, $Count)
{
Write-Host "Uploading file " $file.Name "to" $WorkingFolder.name -ForegroundColor Cyan
if(!($File -like '*.txt')){
#Upload the file
DryRun-UploadFile $WorkingFolder $File $FileSource $Count
}else{
$Count=$Count+1
}
}
}
Function DryRun-Copy-Files{
$AllFolders = Get-ChildItem -Recurse -Path $Folder |? {$_.psIsContainer -eq $True}
#Get a list of all files that exist directly at the root of the folder supplied by the operator
$FilesInRoot = Get-ChildItem -Path $Folder | ? {$_.psIsContainer -eq $False}
#Upload all files in the root of the folder supplied by the operator
Foreach ($File in ($FilesInRoot))
{
#Notify the operator that the file is being uploaded to a specific location
Write-Host "Uploading file " $File.Name "to" $DocLibName -ForegroundColor Cyan
if(!($File -like '*.txt')){
#Upload the file
DryRun-UploadFile($list.RootFolder) $File $null $Count
}else{
$Count=$Count+1
}
}
#Loop through all folders (recursive) that exist within the folder supplied by the operator
foreach($CurrentFolder in $AllFolders)
{
DryRun-PopulateFolder ($list.RootFolder) $FolderRelativePath $Count
}
Write-output "Number of files excluded is: "$Count | Out-file DryRun.txt -append
}
I have removed some of my code for simplicity sake as it has nothing to do with my problem. My code goes through a file structure and counts up if the file is above 160000 bytes or is a txt file. run calling DryRun-Copy-Files.
And I have a variable called $count which I want to use in all the functions and then output what the count is to a file.
The problem is it only counts in the first function DryRun-Copy-Files not in the others
define the variable with global:
$global:count=0
and use it in the functions (don't explicit pass it)