Active directory user shared folder cleanup

I am wanting a script, preferably a batch script but maybe vbscript for an AD user folder cleanup. I am barely learning powershell so I am still gun shy about it. What I am wanting to do is have a script that will generate a list of all users in an OU plus all sub OUs and then parse a list of folders in a folder share, skipping one folder in that share, and if there is a folder for a user that is no longer in AD move that folder and all of its contents to the folder that was skipped in the reading. Also, if there is a user in AD that does not have a folder, create it and give it permission.

Example:
AD users          Shared folders
Sam                  Tom
Tom                  Sally
Sally                  Sam
George             Henry
Mary                 Mary

I would like for the script to move the Henry folder and create the George folder and give user full rights to folder.

I have had a script that should have done that before, but if anything was out of order, then every folder after that would have been moved so I scrapped it. I did a dsquery user to a txt file and then listed all directories in the folder and did a direct comparison.
LVL 13
Gabriel CliftonNet AdminAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Joseph MoodyBlogger and wearer of all hats.Commented:
Too bad you don't want a PowerShell version. :)

This script should do what you need and it is in VB: http://community.spiceworks.com/scripts/show/1865-find-orphaned-ad-home-folders
Gabriel CliftonNet AdminAuthor Commented:
I saw that, but the problem is that the folder is not the home directory, it is just a shared folder that only they have access to and is a mapped drive for the user. I have so much on my plate right now that when I look at it I cannot think of how to change the search for home directory to search for user logon name. I would not mind powershell, but here is what I am looking at on that. I would like full explanation of how it works so that I can learn it and I have no way of signing the scripts and I do not like the idea of decreasing the security of powershell so that I can run the scripts, I have, but I would rather turn it back on.
Gabriel CliftonNet AdminAuthor Commented:
Here is what I came up with this morning, it is crude but working. Always looking for a better solution.

@echo off
cls
echo.
echo Searching for users with no V Drive folder
for /f %%a in ('dsquery user "OU=Staff,DC=domain,DC=local" -o samid -limit 0 ^|sort') do call :srch %%a
pause
goto next
exit /b

:srch
set usr=%1
set usr=%usr:"=%
if not exist "\\server\share\%usr%" md "\\server\share\%usr%" && ping -n 5 localhost >NUL && cacls.exe "\\server\share\%usr%" /t /e /c /g "%usr%@FSISD.LOCAL":f && cacls.exe "\\server\share\%usr%" /t /e /c /g "%usr%@FSISD.LOCAL":f
if not exist "\\server\share\%usr%\%usr%" md "\\server\share\%usr%\%usr%" && ping -n 5 localhost >NUL && cacls.exe "\\server\share\%usr%\%usr%" /t /e /c /g "%usr%@FSISD.LOCAL":f && cacls.exe "\\server\share\%usr%\%usr%" /t /e /c /g "%usr%@FSISD.LOCAL":f
::echo "\\server\share\%usr%" >>%userprofile%\desktop\needsfolder.txt

exit /b



:next
cls
echo.
echo Searching for V Drive folders with no user
for /f %%c in ('dir /b "\\server\share" ^|sort') do call :srch2 %%c
pause
exit /b

:srch2
set fdir=%1
dsquery user "OU=Staff,DC=domain,DC=local" -o samid -limit 0 -samid %fdir% || echo \\server\share\%fdir%>>%userprofile%\desktop\movefolder.txt
exit /b

Open in new window

Acronis True Image 2019 just released!

Create a reliable backup. Make sure you always have dependable copies of your data so you can restore your entire system or individual files.

yo_beeDirector of Information TechnologyCommented:
Even though you did mention the GUN SHY of powershell I think it will be worth a posting for you to use and try.  Look at the script and examine it piece by piece.

##################################################################################
#  Must have RSAT installed on the computer you plan of running this from.       #
#  If you plan on running this from your DC then you are already set with this.  #
##################################################################################

#This gives your Powershell session access  Active Directory Commands

Import-Module ActiveDirectory

##################################################################################
# this will search the path and store all the folders at level one in an  store  #
# the values in an array for future uses.  The $folder is a delcare like used in #
# DIM in VBS.                                                                    #
# If you do not add the pipe and select -expand <value> this will just retun     #
# errors.  You can play around without the pipe and you will see the results     #
##################################################################################
 
 $folders = Get-ChildItem -Path '\\netapp01\UserData\Folders' | Select -expand name

##################################################################################
#    This next step will loop through the array $Folders and for each Folder in  #
#    the array $folder run Get-ADUSER and the $folder is the username in AD      #
#    If the user does not exist the command Remove-Item will delete the folder   #
#    The -Whaif switch is used to test a dry run and see what would happen if    #
#    the user does not exist.  Once you confirm that the script is working       #
#    you can remove the -Whatif and it will that do what you are asking          #
##################################################################################


 
Foreach ($folder in $folders)

 {
    Try
   {
   Get-ADUser -Identity $folder | Select Name -ErrorAction Stop 
   }
    Catch
   {
    $f ='\\netapp01\UserData\Folders\' + $folder
    remove-item -path $f -Recurse -WhatIf 
   }
  
  
 }

Open in new window


with a slight variation of the Get-ADUSer Command like I used the Where-Object = enabled users you can filter out disabled users as well as users that do not exist in AD if you wish to cleanup  disabled users as well


 Get-ADUser -Identity $folder  | Where-Object {$_.enabled -eq $true} |  Select Name -ErrorAction Stop 

Open in new window

Gabriel CliftonNet AdminAuthor Commented:
That looks great for moving directories for users that no longer exists, is there a way to skip folders that do not need to be moved.
yo_beeDirector of Information TechnologyCommented:
Can you give an example?
ie
\\server01\users\<username>\Folders\Desktop
Gabriel CliftonNet AdminAuthor Commented:
OK, we primarily have \\server1\share1\<username> but there are a few folders that once was a user account (hence why the folders are there in the first place) that are now general use folders. I have tried to move the folders out of there before but i got several complaints because people were used to going to \\server1\share1\folder and they could not remember that the folder had moved and had me move it back.
yo_beeDirector of Information TechnologyCommented:
We can put an exclude, but are we dealing with One off basis or is this a general folder that is the same for all users.

ie.

\\server1\share\<username>\FolderA
or will it be
\\server1\share\<username>\FolderA
\\Server1\share\,username>\FolderB
Gabriel CliftonNet AdminAuthor Commented:
No, it is a folder that used to correspond to a username but now is a general folder so it is just \\server01\share01\folder that needs to be excluded. I have at least two of those folders.
yo_beeDirector of Information TechnologyCommented:
Here is what I think you are asking:
Line 41 I added some logic If the variable  $F is not equal to the path in question where the path = $f

##################################################################################
#  Must have RSAT installed on the computer you plan of running this from.       #
#  If you plan on running this from your DC then you are already set with this.  #
##################################################################################

#This gives your Powershell session access  Active Directory Commands

Import-Module ActiveDirectory

##################################################################################
# this will search the path and store all the folders at level one in an  store  #
# the values in an array for future uses.  The $folder is a delcare like used in #
# DIM in VBS.                                                                    #
# If you do not add the pipe and select -expand <value> this will just retun     #
# errors.  You can play around without the pipe and you will see the results     #
##################################################################################
 
 $folders = Get-ChildItem -Path '\\netapp01\UserData\folders' | Select -expand name

##################################################################################
#    This next step will loop through the array $Folders and for each Folder in  #
#    the array $folder run Get-ADUSER and the $folder is the username in AD      #
#    If the user does not exist the command Remove-Item will delete the folder   #
#    The -Whaif switch is used to test a dry run and see what would happen if    #
#    the user does not exist.  Once you confirm that the script is working       #
#    you can remove the -Whatif and it will that do what you are asking          #
##################################################################################


 
Foreach ($folder in $folders)

 {
    Try
   {
   Get-ADUser -Identity $folder -Properties * | Where-Object {$_.enabled -eq $true} |  Select Name -ErrorAction Stop 
   }
    Catch
   {
    $f =  '\\netapp01\UserData\folders\' + $folder
   If ($f -ne '\\netapp01\userdata\folders\DoNotMove')
        {
            remove-item -path $f  -Recurse  -whatif
        }
   }
  
  
 }

Open in new window


Img
Gabriel CliftonNet AdminAuthor Commented:
I have been trying to figure this out over and over, with multiple exclude folders, it does not work for me so i am sure I am doing something wrong. Here is what I have tried.

   If (($f -ne '\\netapp01\userdata\folders\DoNotMove 1') -or ($f -ne '\\netapp01\userdata\folders\DoNotMove 2') -or ($f -ne '\\netapp01\userdata\folders\DoNotMove 3'))

and

   If ($f -ne '\\netapp01\userdata\folders\DoNotMove 1' -or $f -ne '\\netapp01\userdata\folders\DoNotMove 2' -or $f -ne '\\netapp01\userdata\folders\DoNotMove 3')
yo_beeDirector of Information TechnologyCommented:
I added a Where-Object to the foreach loop to filter out folders that are like a certain name like DoNotMove.  This replaces the IF part of the script.

##################################################################################
#  Must have RSAT installed on the computer you plan of running this from.       #
#  If you plan on running this from your DC then you are already set with this.  #
##################################################################################

#This gives your Powershell session access  Active Directory Commands

Import-Module ActiveDirectory

##################################################################################
# this will search the path and store all the folders at level one in an  store  #
# the values in an array for future uses.  The $folder is a delcare like used in #
# DIM in VBS.                                                                    #
# If you do not add the pipe and select -expand <value> this will just retun     #
# errors.  You can play around without the pipe and you will see the results     #
##################################################################################
 
 $folders = Get-ChildItem -Path '\\netapp01\UserData\folders' | Select -expand name

##################################################################################
#    This next step will loop through the array $Folders and for each Folder in  #
#    the array $folder run Get-ADUSER and the $folder is the username in AD      #
#    If the user does not exist the command Remove-Item will delete the folder   #
#    The -Whaif switch is used to test a dry run and see what would happen if    #
#    the user does not exist.  Once you confirm that the script is working       #
#    you can remove the -Whatif and it will that do what you are asking          #
##################################################################################


 
Foreach ($folder in ($folders| Where-Object {$_ -notlike '*DoNotMove*'})) 

 {
    Try
   {
   Get-ADUser -Identity $folder -Properties * | Where-Object {$_.enabled -eq $true} |  Select Name -ErrorAction Stop 
   }
    Catch
   {
   $folder
    $f =  '\\netapp01\UserData\folders\' + $folder
#################################################
#  The  IF Then Statement has been remarked out because of the   #
# where-object in the ForEach Loop                                                       #
#################################################

  # If ($f -like '\\netapp01\userdata\folders\DoNotMove*')
        {
           
            remove-item -path $f  -Recurse -WhatIf
        }
   }
  
  
 }

Open in new window

yo_beeDirector of Information TechnologyCommented:
Have you tried adjustment yet?
You can also put the Where-Object part in the Line 18:

Also I thought this question had an accepted answer.

##################################################################################
#  Must have RSAT installed on the computer you plan of running this from.       #
#  If you plan on running this from your DC then you are already set with this.  #
##################################################################################

#This gives your Powershell session access  Active Directory Commands

Import-Module ActiveDirectory

##################################################################################
# this will search the path and store all the folders at level one in an  store  #
# the values in an array for future uses.  The $folder is a delcare like used in #
# DIM in VBS.                                                                    #
# If you do not add the pipe and select -expand <value> this will just retun     #
# errors.  You can play around without the pipe and you will see the results     #
##################################################################################
 
 $folders = Get-ChildItem -Path '\\netapp01\UserData\folders' | Where-Object {$_.name -notlike '*DoNotMove*'}| Select -expand name

##################################################################################
#    This next step will loop through the array $Folders and for each Folder in  #
#    the array $folder run Get-ADUSER and the $folder is the username in AD      #
#    If the user does not exist the command Remove-Item will delete the folder   #
#    The -Whaif switch is used to test a dry run and see what would happen if    #
#    the user does not exist.  Once you confirm that the script is working       #
#    you can remove the -Whatif and it will that do what you are asking          #
##################################################################################


 
Foreach ($folder in $folders) 

 {
    Try
   {
   Get-ADUser -Identity $folder -Properties * | Where-Object {$_.enabled -eq $true} |  Select Name -ErrorAction Stop 
   }
    Catch
   {
   $folder
    $f =  '\\netapp01\UserData\folders\' + $folder
    $F
    #If ($f -like '\\netapp01\userdata\folders\DoNotMove*')
        
           
            remove-item $f -Recurse -WhatIf
        
   }
  
  
 }

Open in new window

Gabriel CliftonNet AdminAuthor Commented:
I have an issue with the latest code, so I am trying to work it out on my own before asking for more help.
yo_beeDirector of Information TechnologyCommented:
Ok.  I did posted a slightly modified script from all the previous ones.

Also thanks to you  inquiry you got me doing something I should have done a long time ago (Clean up stale user data)
Gabriel CliftonNet AdminAuthor Commented:
Interestingly, I still keep getting What if: Performing the operation "Remove Directory" on target  \\server\share on every directory I exclude.
yo_beeDirector of Information TechnologyCommented:
Can you post your script?
Gabriel CliftonNet AdminAuthor Commented:
##################################################################################
#  Must have RSAT installed on the computer you plan of running this from.       #
#  If you plan on running this from your DC then you are already set with this.  #
##################################################################################

#This gives your Powershell session access  Active Directory Commands

Import-Module ActiveDirectory

##################################################################################
# this will search the path and store all the folders at level one in an  store  #
# the values in an array for future uses.  The $folder is a delcare like used in #
# DIM in VBS.                                                                    #
# If you do not add the pipe and select -expand <value> this will just retun     #
# errors.  You can play around without the pipe and you will see the results     #
##################################################################################
 
 $folders = Get-ChildItem -Path '\\netapp01\UserData\folders' | Where-Object {$_.name -notlike 'Transport' -or $_.Name -notlike 'Inactive Users' -or $_.Name -notlike 'transfinder'}| Select -expand name

##################################################################################
#    This next step will loop through the array $Folders and for each Folder in  #
#    the array $folder run Get-ADUSER and the $folder is the username in AD      #
#    If the user does not exist the command Remove-Item will delete the folder   #
#    The -Whaif switch is used to test a dry run and see what would happen if    #
#    the user does not exist.  Once you confirm that the script is working       #
#    you can remove the -Whatif and it will that do what you are asking          #
##################################################################################


 
Foreach ($folder in $folders) 

 {
    Try
   {
   Get-ADUser -Identity $folder -Properties * | Where-Object {$_.enabled -eq $true} |  Select Name -ErrorAction Stop 
   }
    Catch
   {
   $folder
    $f =  '\\netapp01\UserData\folders\' + $folder
    $F
    #If ($f -like '\\netapp01\userdata\folders\DoNotMove*')
        
           
            remove-item $f -Recurse -WhatIf
        
   }
  
  
 }

Open in new window

yo_beeDirector of Information TechnologyCommented:
Try putting the * before and after each filter

ie. '*transport*'

The * is a wildcard. So anything before Transport and after does not matter and will be filtered.

ie. \\blah\blah\transport\blah or \\blah\blah\transport blah\blah will be filtered

If you filter like this *\transport\*
\\blah\blah\transport\blah  will be filtered, but \\blah\blah\transport blah\blah will not be filtered
Gabriel CliftonNet AdminAuthor Commented:
I have tried that with the same result. This is with the wildcards as *transport*
transfinder
\\server\share\transfinder
What if: Performing the operation "Remove Directory" on target "\\server\share\transfinder".
Transport
\\server\share\Transport
What if: Performing the operation "Remove Directory" on target "\\server\share\Transport".
yo_beeDirector of Information TechnologyCommented:
Are you seeing any Transports in your list.
I would recommend starting with just a single filter and remove all other -or clauses
yo_beeDirector of Information TechnologyCommented:
This is to isolate your workflow
Gabriel CliftonNet AdminAuthor Commented:
Worked with single exclusion. Changed the -or to -and and it worked, which to me is not logical because I am not looking for folders with all three to exclude.
yo_beeDirector of Information TechnologyCommented:
The logic would seem to be if it is this or that, but I am thinking that the first part of the $folders array if collecting all the folders name then filtering the items.

Say we have a  bucket that we used to collect different fruit and after we collected the fruit we wanted to remove some.  We do not want Apples or  Peaches  so we then remove where there are apples and peaches.  That is the only logic I have to explain this.
Gabriel CliftonNet AdminAuthor Commented:
Best explanation I have is that it is not logic, but Microsoft logic. Now how do we add the next part of making sure that if a user does exist make sure they have a folder and full rights to their folder?
yo_beeDirector of Information TechnologyCommented:
Are you looking to move the items into another parent folder?
\\server\fileshare\Archive\ExUser1
\\server\fileshare\Archive\ExUser2
\\server\fileshare\Archive\ExUser3

If so your folders that move into there should take on the archive solves NTFS Security.

change Line 46: from remove-item to Move-Item -path source -destination  \\server\fileshare\Archive\ + $folder -Force -Whatif
Steven CarnahanNetwork ManagerCommented:
Rule of thumb when moving/copying files/folders:

If you move a file/folder on the same volume it retains the NTFS permissions of the original location.

If you copy a file/folder on the same volume it inherits the NTFS permissions of the target location.

Microsoft's wording:

By default, an object inherits permissions from its parent object, either at the time of creation or when it is copied or moved to its parent folder. The only exception to this rule occurs when you move an object to a different folder on the same volume. In this case, the original permissions are retained.
Gabriel CliftonNet AdminAuthor Commented:
Sorry it took so long to post back, getting ready for school to start. First, I do not care if the moved folder retains permissions because sometimes the teacher comes back so the only thing I have to do is re-enable the account and move the folder back and all is good. Second, when I attempted Move-Item -path source -destination  \\server\fileshare\Archive\ + $folder -Force -Whatif, I kept getting errors and after some digging I changed it to Move-Item -path source -destination  \\server\fileshare\Archive\ -Force -Whatif and it worked. The only issue I had after that was that if there was a folder in the destination with the same name as the folder I was moving from a failed attempt to move, it would fail to move the folder.
yo_beeDirector of Information TechnologyCommented:
So let say you have
\\server\fileshare\Archive\ExUser1
 \\server\fileshare\Archive\ExUser2
 \\server\fileshare\Archive\ExUser3   , but \\server\fileshare\Archive\ExUser3 already exist.  Is that what you are say?
Gabriel CliftonNet AdminAuthor Commented:
Moving \\server\share\exuser1 to \\server\share\archive\exuser1 but \\server\share\archive\exuser1 already exists.
yo_beeDirector of Information TechnologyCommented:
So I decided to take a difference route and leverage something I came across when I wanted to leverage Powershell to copy files with longer fullname than 260 characters.

Combined both Powershell and Robocopy.

##################################################################################
#  Must have RSAT installed on the computer you plan of running this from.       #
#  If you plan on running this from your DC then you are already set with this.  #
##################################################################################

#This gives your Powershell session access  Active Directory Commands

Import-Module ActiveDirectory

##################################################################################
# this will search the path and store all the folders at level one in an  store  #
# the values in an array for future uses.  The $folder is a declare like used in #
# DIM in VBS.                                                                    #
# If you do not add the pipe and select -expand <value> this will just return     #
# errors.  You can play around without the pipe and you will see the results     #
##################################################################################
 
 $folders = Get-ChildItem -Path '\\netapp01\UserData\folders' | Where-Object {$_.name -notlike '*BlahBlah*'}| Select -expand name
 #$Dest = '\\netapp01\UserData\Test'

##################################################################################
#    This next step will loop through the array $Folders and for each Folder in  #
#    the array $folder run Get-ADUSER and the $folder is the username in AD      #
#    If the user does not exist or the user has been disabled the command        #
#    Remove-Item will delete the folder.                                         #
#    The Try/Catch will try Get-ADUSER and if there is an error caused by a      #
#    username not existing or the user is disabled the Catch will be invoked     #
#    Catch will run the Remove-item that is the $f which is the folder path      #
#    The -Whaif switch is used to test a dry run and see what would happen if    #
#    the user does not exist.  Once you confirm that the script is working       #
#    you can remove the -Whatif and it will that do what you are asking          #
##################################################################################


 
Foreach ($folder in ($folders | Where-Object {$_ -like '*move*'}) )

 {

        Try
   {
            Get-ADUser -Identity $folder -Properties * | Where-Object {$_.enabled -eq $true} |  Select Name -ErrorAction Stop 
   }
        Catch
   {
   
   ##################################################################################
   # used to varify that the folder name that is being processed.                   #
   # This is not needed to run the script correctly                                 #
   ##################################################################################

        $folder 

   ##################################################################################
   #  This next line is need to parse the entire folder path for the next           #
   #  command to remove the directory path                                          #
   #                                                                                #
   ##################################################################################
   

       
       $source = join-path '\\netapp01\UserData\Folders' $folder
       $dest = join-path \\netapp01\UserData\Test $folder




 Robocopy  $source $dest  /e /xo /move /w:0 /R:0 
  

      
#
  
   }
  
  
 }

Open in new window

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Gabriel CliftonNet AdminAuthor Commented:
I have not forgotten about this, have not taken a look yet. I have shattered a bone in my foot and have had several pre-surgery doctor visits.
yo_beeDirector of Information TechnologyCommented:
:(

That sucks .  Get well soon
Gabriel CliftonNet AdminAuthor Commented:
Moderator, this is not abandoned, unable to get to it right now.
Gabriel CliftonNet AdminAuthor Commented:
I finally got a chance to look at your final code, it worked great! I have to say it is much faster than doing this by batch script. So, with powershell, how do I tie in the second part of my original question.
Also, if there is a user in AD that does not have a folder, create it and give it permission.

Example:
AD users          Shared folders
Sam                  Tom
Tom                  Sally
Sally                  Sam
George             Henry
Mary                 Mary

I would like for the script to move the Henry folder and create the George folder and give user full rights to folder. I have started playing with powershell a little, but I can't get used to it, yet.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Active Directory

From novice to tech pro — start learning today.