Sysadmins of the North

Technical blog, where topics include: computer, server, web, sysadmin, MySQL, database, virtualization, optimization and security

PowerShell: find all files owned by a particular user

In Windows, you sometimes need to find all files owned by a specific user. Recursively on your Windows Server NTFS file system. PowerShell has some nice cmdlets and features to automate this task for you. Here you’ll find example PowerShell scripts to find and list files owned by a specific user…

PowerShell 5.0
PowerShell 5.0

Find files owned by a user with PowerShell

Here is the example PowerShell script to list files owned by a user, in Windows Server and recursively.

Later on we’ll dive in to see what this PowerShell snippet does.

[String]$username = "[username]"
[String]$outfile = "[output_file_path]"
$path = Get-ChildItem "." -Recurse
Foreach( $file in $path ) {
	$f = Get-Acl $file.FullName
	if( $f.Owner -eq $username ) {
		Write-Host( "{0}"-f $file.FullName | Out-File `
			-Encoding "UTF8" `
			-FilePath $outfile -Append)
	}
}

Don’t forget to fill out the variables [username] and [output_file_path]. Results are logged to a file.

Some reformatting was done in this code snippet.

PowerShell Cmdlets

Cmdlets are the heart-and-soul of Windows PowerShell. A cmdlet is a lightweight command that is used in the Windows PowerShell environment. The Windows PowerShell runtime invokes these cmdlets within the context of automation scripts that are provided at the command line. The Windows PowerShell runtime also invokes them programmatically through Windows PowerShell APIs.

Find files owned by a user – script explanation

What the above PowerShell script -to find all files owned by a particular user- does is pretty straightforward. First we define a $username to search for, which can be either an AD user or local user. And we define a path for our results logfile with $outfile. Both are of the type String.

This may interest you:   .svc WCF web service returns 404 Not Found on IIS 8

The Cmdlet Get-ChildItem is used to get the items and child items (folders and files) in a specified location. The specified location is the current directory: ".". Since we want to find all files, we recurse into subdirectories using the -Recurse parameter.

The result – all files – is stored into the $path variable, through which we loop with Foreach.

Within our PowerShell Foreach loop, the Get-Acl Cmdlet is used to retrieve the ACL’s, or Access Control Lists, of that file or directory. E.g, the “permissions”. We only want the files owned by the specified user, for which we use the Owner property. The file (or folder) path itself is stored in .FullName.

When we’ve found a match (if ( $f.Owner -eq $username )), the result is written to our logfile with Write-Host and a piped Out-File.

Get-ChildItem memory usage

Yes, this example PowerShell script can use a lot of memory when run on a directory with millions of files. Use with care.

PowerShell Cmdlets Recursiveness: Why use Get-ChildItem?

You might wonder why we first use Get-ChildItem to dive into a file system before using Get-Acl? Simple: on the “Hey, Scripting Guy” blog we can read that Get-Acl doesn’t accept a sort of -Recurse parameter, that would enable you to retrieve the owners of all the files located in any subfolder. The Get-ChildItem cmdlet does accept the -Recurse parameter.

This may interest you:   Fatal error: Uncaught Error: [] operator not supported for strings - PHP 7.1

PowerShell Cmdlets used

Here are all PowerShell Cmdlets used in this script:

Pretty simple right? :)

Get-ChildItem and Get-Acl one-liner

The above can also be accomplished in a one-liner:

Get-ChildItem "."  -force -Recurse `
	-ErrorAction 'SilentlyContinue' | `
	Get-Acl | Where-Object{ `
		$_.Owner -eq "[username]" `
	} | Format-List -Property PsPath

Here, -erroraction 'silentlycontinue' is used to suppress PowerShell errors from being printed. Some formatting was done in this code snippet.

cmd.exe list owner of directory or file in Windows

In a cmd.exe command-line shell, you can use dir /Q to display the file owner. Combine this with /S to display files in the specified directory and subdirectories (e.g recursive), and/or /AD to only list directories.

3 Comments

  1. I’ve put the script in a .ps file and launched with powershell – there is no registration of a file (outfile name = H:\Data\old\file-user.txt and username =name.lastname). When powershell is ending, the scriptfile is opening himself. what i going wrong ?

  2. Question on expanding owner -eq username. I am working on taking your snippet and incorporating it in a larger script that searches directories for specific owners and moves them to an offboarding folder so that domain\user1 owned files gets moved to offboarding\user1 domain\user2 files get moved to offboarding\user2 etc. The issue I am having is feeding more than one user to $_.Owner -eq “[username]”. If I change the operator to -match I can feed it “domain\\user1|domain\\user2” but that has the issue of also finding files for domain\user12 since that matches. So I tried Where-Object{ foreach ($user in $users) {$_.Owner -eq $user}} in the statement but that does not work either.
    Running the original snippet multiple times per user would be slow due to the number of files being searched.
    Do you have any suggestions?

    • I found my answer. By changing it to Where-Object {$_.Owner -in $users } with $users being an array I can find files of multiple users at the same time.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.