Using Powershell to export the NTFS security permissions - powershell

Using Powershell, how can I get the list of Folders in D: drive with Everyone access explicitly defined?
I've installed the module below, but not sure how to arrange the command and export it to .CSV file.
https://ntfssecurity.readthedocs.io/en/latest/
https://devblogs.microsoft.com/scripting/weekend-scripter-use-powershell-to-get-add-and-remove-ntfs-permissions/

It somewhat depends on what you want the export to look like. However, the below example is a starting point:
$StartPath = "C:\temp\08-28-19"
Get-ChildItem $StartPath |
Get-NTFSAccess -Account Everyone |
Select-Object FullName,Account,AccessRights,Type |
Export-Csv c:\temp\PermExport.csv -NoTypeInformation
So you/we may have to work on the Select-Object command. Please update the question with an example of desired output and we'll workshop this more.
Note: there are some complications if there's a risk of paths longer than 260 characters. The NTFSSecurity module includes commands like Get-ChildItem2 which are based on the AlphaFS .Net libraries. However, there are some bugs around naming, which are documented in this GitHub issue I briefly reported into.
However, you can use an alternate syntax with good-old Get-ChildItem to list long paths. That might look something like this:
For UNC's:
Get-ChildItem '\\?\UNC\<ServerName>\Share\RemainingPath' -Recurse |
...
For Local Drives:
Get-ChildItem '\\?\c:\temp' -Recurse |
...

Related

Apply setCaseSensitiveInfo recursively to all folders and subfolders

I am trying to configure my dotnet core project (in Windows) as "case sensitive", so it behaves as in my production server (linux).
I have found this way of doing it:
fsutil.exe file setCaseSensitiveInfo "C:\my folder" enable
The problem is that this function is not recursive:
The case sensitivity flag only affects the specific folder to which you apply it. It isn’t automatically inherited by that folder’s subfolders.
So I am trying to build a powershell script that applies this to all folders and subfolders, recursively.
I have tried googling something similar and just modifying the command line, but I don't seem to find the corrent keywords. This is the closest that I've gotten to this sort of example.
Correct code:
(Get-ChildItem -Recurse -Directory).FullName | ForEach-Object {fsutil.exe file setCaseSensitiveInfo $_ enable}
Explanation:
NOTE: The code in the answer assumes you're in the root of the directory tree and you want to run fsutil.exe against all the folders inside, as it's been pointed out in the comments (thanks #Abhishek Anand!)
Get-ChildItem -Recurse -Directory will give you list of all folders (recursively).
As you want to pass their full path, you can access it by using .FullName[1] (or more self-explanatory | Select-Object -ExpandProperty FullName ).
Then you use ForEach-Object to run fsutil.exe multiple times. Current file's FullName can be accessed using $_ (this represents current object in ForEach-Object)[2].
Hint:
If you want more tracking of what's currently being processed you can add the following to write the path of currently processed file to the console: ; Write-Host $_ (semicolon ; is to separate from fsutil invocation) as it was pointed out in the comments (thanks Fund Monica's Lawsuit !)
[1] .FullName notation works for PowerShell 3.0 and greater, Select-Object -ExpandProperty FullName is preferred if there's a chance that lower version will be used.
[2] $_ is an alias for $PSItem
(Get-ChildItem -Recurse -Directory).FullName | ForEach-Object {if (-Not ($_ -like '*node_modules*')) { fsutil.exe file setCaseSensitiveInfo $_ enable } }
I modified #robdy's code to allow excluding node_modules. You can replace the "node_modules" bit in the above with anything to exclude filepaths containing it.
If you're working with npm, you probably want to exclude node_modules. #robdy's answer is great, but was taking minutes at a time iterating over every single node package folder even if I didn't have the package installed; given that this is something one might want to run fairly often since directories might be added all the time, and since you probably aren't modifying anything in node_modules, excluding it seems reasonable.
With Cygwin and bash shell, you can do this:
$ find $THEDIR -type d -exec fsutil file setCaseSensitiveInfo "{}" enable \;
It appears that Windows handles the '/' characters output by the find command just fine.
In my case I had to first enable the Linux subsystem before using the fsutil tool. So my steps were:
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
then restart, and then #robdy 's solution:
(Get-ChildItem -Recurse -Directory).FullName | ForEach-Object {fsutil.exe file setCaseSensitiveInfo $_ enable}
On windows 11, the other answers are not correct, as fsutil requires that the directory is not empty. To overcome this, I created a NEW empty directory, used fsutil file setCaseSensitiveInfo to set the case sensitive flag on the new directory, then MOVED the files from the other directory inside the new one. This works, as the directories are re-created when moved, and new directories inherit the case sensitive flag.

How do I prevent Get-ChildItem from traversing a particular directory?

Let me start by saying that I've looked at Unable to exclude directory using Get-ChildItem -Exclude parameter in Powershell and How can I exclude multiple folders using Get-ChildItem -exclude?. Neither of these has an answer that solves my problem.
I need to search a directory recursively for files with a certain extension. For simplicity, let's just say I need to find *.txt. Normally, this command would suffice:
Get-ChildItem -Path 'C:\mysearchdir\' -Filter '*.txt' -Recurse
But I have a major problem. There's a node_modules directory buried somewhere inside C:\mysearchdir\, and NPM creates extremely deep nested directories. (The detail of it being an NPM managed directory is only important because this means the depth is beyond my control.) This results in the following error:
Get-ChildItem : The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.
I believe this error bubbles up from the limitations in the .NET IO libraries.
I can't search in the other directories around it very easily. It's not at the top of the directory; it's deeper in, say at C:\mysearchdir\dir1\dir2\dir3\node_modules, and there are directories I need to search at all those levels. So just searching the other directories around it is going to be cumbersome and not very maintainable as more files and directories are added.
I've tried to -Exclude parameter without any success. That isn't surprising since I just read that -Exclude is only applied after the results are fetched. I can't find any real info on using -Filter (as is noted in this answer).
Is there any way I can get Get-ChildItem to work, or am I stuck writing my own recursive traversal?
Oh, man, I feel dumb. I was facing the same problem as you. I was working with #DarkLite1's answer, trying to parse it, when I got to the "-EA SilentlyContinue" part.
FACEPALM!
That's all you need!
This worked for me, try it out:
Get-ChildItem -Path 'C:\mysearchdir\' -Filter '*.txt' -Recurse -ErrorAction SilentlyContinue
Note: This will not exclude node_modules from a search, just hide any errors generated by traversing the long paths. If you need to exclude it entirely, you're going to need a more complicated solution.
Maybe you could try something like this:
$Source = 'S:\Prod'
$Exclude = #('S:\Prod\Dir 1', 'S:\Prod\Dir 2')
Get-ChildItem -LiteralPath $Source -Directory -Recurse -PipelineVariable Dir -EV e -EA SilentlyContinue |
Where {($Exclude | Where {($Dir.FullName -eq "$_") -or ($Dir.FullName -like "$_\*")}).count -eq 0}

get the latest created folder from a path using powershell

How to get the latest created folder from a path using Windows PowerShell?
I have the path C:\temp and I want to find the most recently created folder in this path.
PowerShell works mainly with the pipeline, so most of what you'd write will consist of creating objects representing some information, and filtering and manipulating them. In this case, the objects are a bunch of folders.
Get all items in the folder. This will get files and folders, that's why step 2 is necessary. The | at the end of the line signals that the pipeline will continue in the next line – objects created by Get-ChildItem will then be passed one by one to another command.
Get-ChildItem c:\temp |
Filter for folders. There is no really elegant way, sadly. Don't worry about that it says “container”, not “folder” – Those commands work with many different things, not only files and folders, so a more general concept was used in naming.
Where { $_.PSIsContainer } |
Sort by date, descending, so the newest folder is the first one.
Sort CreationTime -Descending |
Select the first (newest) folder.
Select -First 1
So in short:
gci c:\temp | ? { $_.PSIsContainer } | sort CreationTime -desc | select -f 1
or
(gci c:\temp | ? { $_.PSIsContainer } | sort CreationTime)[-1]
Both of those lines make heavy use of default aliases for commands in PowerShell, such as ? for Where-Object. You should use the full names in scripts, though, as you'll never know what the aliases will look like on other machines the code might run on.
EDIT: PowerShell 3 has additional parameters for Get-ChildItem that allow you to do filtering for files or folders directly, so you don't need the Where:
Get-ChildItem -Directory C:\temp | ...
Generally you will work with objects and their properties in PowerShell. Two very helpful commands are Get-Member and its alias gm and Get-Command or just gcm. Get-Member will tell you what properties and methods an object has; you just pipe something else into it for that:
Get-ChildItem | gm
will tell you what properties files and directories have.
Get-Command will list all commands there are or those that match a particular pattern. PowerShell commands try to be very consistent in their use of verbs and nouns. To find all commands that end in Object you can try gcm *-Object – those are general commands working with pretty much everything. Get-Help ForEach-Object then would tell you about a particular command, ForEach-Object in this case.

How can this way exclusion of files be achieved in PowerShell?

I have a PowerShell script on a production server to show me the list of database backup files that are older than 30 days.
I need to see only the files that have the extension of ".bak". However, in my script there is no matching syntax or regular expression, so I am also getting to see a list of files which have an extension like "filename.foo.bak". These files may be text files or other configuration files on the server for which backups have been taken automatically by the program that uses these files.
How do I enable a match filter so that I see only "*.bak" and not other files as mentioned above?
As mentioned by mjolinor, I have used this script to do the exclusion.
gci $paths -recurse -filter *.bak -exclude *.*.bak | ?{!$_.psiscontainer}
However, I have learnt that I need to exclude some system folders such as C:\Windows.
How can this be accomplished as well?
Try this:
gci *.bak -exclude *.*.bak
I tried to reply to your comment, but the code doesn't show up right. -exclude takes a string[] argument, so:
gci -recurse -filter *.bak -exclude *.*.bak,windows |? {!$_.psiscontainer}

Get powershell to display all paths where a certain file can be found on a drive

I'm trying to build a function that will show me all path's where a certain filename is located. The function would take one parameter, that being the file name.
The result would be either a list of all paths, or a message saying there's no such file on the system.
I'm new to Powershell, and I'm not getting the syntax just yet.
I've tried this:
Get-ChildItem -Path -Include notepad.exe
But that threw an error message. I'm currently trying:
$i="notepad.exe"
Foreach ($i in Get-ChildItem c:\ -Recurse){echo -Path}
Started that now, it's still running, don't know what'll happen, really.
EDIT: echo'd an enormous amount of lines that just say "-Path"...
Can anybody help with this problem? I'm running Powershell 1.0 by the way.
So, to explain what I wish to see when executing this command, here is an example of what I expect after looking for *.txt:
C:/foo.txt
C:/A/foobar.txt
C:/A1/foo.txt
And so on, listing the path to all .txt files on my harddrive. Only the paths, one per line, no extra info needed.
EDIT2:
I've done it. I'm gonna leave this question up for those who make look for this in the future.
The function I used was this(this specific example will hand you a list of all .zip files on your harddrive, edit where needed):
Get-ChildItem -Path c:\ -Include "*.zip" -Recurse -Force -Name > c:\listOfPaths.txt
This created a file called listOfPaths.txt on my C:\ folder and this contained a list of all occurences of any file ending with .zip in all subfolders of my harddrive.
The "c:\" bit isn't mentioned, but I don't mind.
EDIT3:
thanks capar for a more complete version.
Here is capar's code(or how I got it to work, since Get-Children doesn't work in 1.0)
Get-ChildItem -Path c:\ -Recurse *.txt | Select-Object -Property FullName
Since it's Friday night, I decided to play with Power Shell to see if I can help :)
This comes pretty close to what you are asking for I think:
Get-ChildItem -Path c:\ -Recurse *.txt | Select-Object -Property FullName
If it helps, this command will list the properties of any object that will be returned by Get-ChildItem:
Get-ChildItem | Get-Member
ls c:\ -r | ? {$_.name -eq "notepad.exe"}
Get-Children is not recognized in Powershell V3 either. It would be great if someone removed that bad example.
As a warning to anyone searching for files: C:\ on today's hard drives will take a long time to run. You are well advised to narrow your search as much as you can. Since your folder structure might include spaces or special characters, use the typewriter quote (") or apostrophe (') delimeters.
$mylistoffiles = Get-ChildItem -Path 'C:\Windows\Setup\Scripts' -Recurse *.cmd | Select-Object -Property FullName
$mylistoffiles