I need to change a lot of sub folders's ACL rights. The folders all have the same name "06 - Offers". I've found a powershell command to "copy past" the acl rights from one folder to another. I wonder if anybody here can point me in the right direction to automate this?
It would need to search in a defined folder and change all the access rights for a specific folder in each of it's sub folders (if that makes sense).
(Get-Item 'C:\testfolder').GetAccessControl("Access") | Set-Acl -Path 'D:\realfolder'
So for example we have the folders:
D:\project\project1\06offers
D:\project\project2\06offers
d:\project\project3\06offers
etc...
And all the 06offers folders need the exact same ACL rights.
With this you should be able to create a solution which fits for you:
#Get "example" rights
$PathToExampleFolder = "PathToFile"
$MasterACL = (Get-Item $PathToExampleFolder).GetAccessControl("Access")
#Search all folders
$Folders = Get-ChildItem -Path "PathWhereTheFoldersAre" -Recurse -Filter "06offers"
#Set ACL
foreach ($folder in $Folders) {
Set-Acl -Path $folder.Fullname -AclObject $MasterACL
}
Related
I want to create a new SMB Share for every folder in a directory under windows, have the smb share name be the same as the folder name and set the account "Everyone" with "Full Acess" for the share permission (so not the NTFS permissions)
So for example I have the following folders
Folder1
Folder2
Folder3
And the share names should then be named adequately, so Folder1, Folder2, Folder3
I know how to create a single smb share and set a local user with full access with the following:
New-SmbShare -name "Test" -path "D:\Test" -FullAccess "TestServer\TestAccount"
Where I currently fail is to somehow get all the folder names and create a share accordingly. Also, I don't know how to tell PowerShell the account "Everyone".
EDIT:
When I try it as you mentioned, I get the following error
New-SmbShare: The trust relationship between this workstation and the primary domain failed.
At line:2 char:1
+ New-SmbShare -Name $_.Name -Path $._FullName -FullAccess Everyone
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (MSFT_SMBShare:ROOT/Microsoft/Windows/SMB/MSFT_SMBShare) [New-SmbShare], CimException
+ FullyQualifiedErrorId : Windows System Error 1789,New-SmbShare
Since I can set the permission for this group manually, I dont know why I here would need access to the domain.
I know that the Well-Known SID "World" or "Everyone" has the String Value S-1-1-0, maybe you have to replace "-FullAccess Everyone" with "FullAccess S-1-1-0"? But that didn't work for me..
Source:
https://learn.microsoft.com/en-us/windows/win32/secauthz/well-known-sids
EDIT2
OS is in german, so I have to change "Everyone" to the german counterpart (="Jeder")
Use Get-ChildItem -Directory to enumerate all the folders:
Get-ChildItem path\to\root\directory -Directory |ForEach-Object {
New-SmbShare -Name $_.Name -Path $_.FullName -FullAccess Everyone
}
To generate the correct translation of Everyone regardless of OS language, use its well-known SID:
$everyoneSID = [System.Security.Principal.SecurityIdentifier]::new('S-1-1-0')
$everyoneName = $everyoneSID.Translate([System.Security.Principal.NTAccount]).Value
Get-ChildItem path\to\root\directory -Directory |ForEach-Object {
New-SmbShare -Name $_.Name -Path $_.FullName -FullAccess $everyoneName
}
First of all: sorry for my bad english.
So, I need to create various reports with all permissions of specified folders.
After some search I found 2 ways.
One is using AccessEnum, that it's almost perfect but it doesn't export all permissions, only the folders that have different permission from the root folder. And I need all of them, even if they are the same of the root folder.
The second one is better, a powershell script, but has one weakness: too much recursive, and one of the folders had an output report of 7GB. Holy shirt.
What I need: to modify the script to go deep only for 3 levels of subfolders, for example:
"C:\Folder1" contains various subfolders but I want the script to go deep only to "C:\Folder1\Folder2\Folder3\"
How can I do it?
This is the script:
dir -Recurse "C:\FOLDER" | where { $_.PsIsContainer } | % { $path1 = $_.fullname; Get-Acl $_.Fullname | % { $_.access | Add-Member -MemberType NoteProperty '.\Application Data' -Value $path1 -passthru }} | Export-Csv "C:\REPORT.csv"
Use
Get-Childitem
instead. It has a Depth-Parameter and you can only include Folders.
Reference:
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-childitem?view=powershell-7
I'm new to powershell and I want to check if file in readable and regular. In unix we can do it in one line by using -f & -r. For example the following shell script function accepts filename as argument and checks the readability and regularity of file, whats the powershell equivalent for this?
_ChkRegularFile_R() # checks whether a file is regular and readable
{
_CRFRfilename=$1 # name of the file to be checked
_CRFRsts=1 # default is error
if [ -f "$_CRFRfilename" ]
then
if [ -r "$_CRFRfilename" ]
then
_CRFRsts=0 # success: regular file is readable
fi
fi
return $_CRFRsts
}
To test if a file is readable, you try to open it. If you get an error, then it's not readable. You need to either trap or catch exceptions or stop on errors, as appropriate. Remember, Windows locks files that are open for writing, so applications need to expect that they sometimes can't open a file.
If you absolutely have to, you can use something like this to test if you can read a file:
try {
[System.IO.File]::OpenRead($FullPathName).Close()
$Readable = $true
}
catch {
$Readable = $false
}
And this to test if you can write to a file:
try {
[System.IO.File]::OpenWrite($FullPathName).Close()
$Writable = $true
}
catch {
$Writable = $false
}
That logic is fairly easy to wrap into a function if you really need it.
As far as file types, nearly everything in the file system in Windows is a plain file or a directory, since Windows doesn't have the "everything is a file" convention. So, normally you can test as follows:
# Test if file-like
Test-Path -Path $Path -Leaf
# Test if directory-like
Test-Path -Path $Path -Container
If you're working with a FileInfo or DirectoryInfo object (i.e., the output of Get-Item, Get-ChildItem, or a similar object representing a file or directory) you'll have the PSIsContainer property which will tell you if the item is a file or a directory.
That covers probably 99.999% of cases.
However, if you need to know if something is an NTFS hard link to a file (rare, but oldest), an NTFS junction to a directory, an NTFS symlink, an NTFS volume mount point, or any type of NTFS reparse point, it gets much more complicated. [This answer does a good job describing the first three.]
Let's create a simple NTFS folder to test with:
# Create a test directory and change to it.
New-Item -Path C:\linktest -ItemType Directory | Select-Object -ExpandProperty FullName | Push-Location
# Create an empty file
New-Item -Path .\file1 -ItemType file -Value $null | Out-Null
New-Item -Path .\file2 -ItemType file -Value $null | Out-Null
# Create a directory
New-Item -Path .\dir1 -ItemType Directory | Out-Null
# Create a symlink to the file
New-Item -ItemType SymbolicLink -Path .\sfile1 -Value .\file1 | Out-Null
# Create a symlink to the folder
New-Item -ItemType SymbolicLink -Path .\sdir1 -Value .\dir1 | Out-Null
# Create a hard link to the file
New-Item -ItemType HardLink -Path .\hfile1 -Value .\file1 | Out-Null
# Create a junction to the folder
New-Item -ItemType Junction -Path .\jdir1 -Value .\dir1 | Out-Null
# View the item properties
Get-ChildItem -Path . | Sort-Object Name | Format-Table -Property Name, PSIsContainer, LinkType, Target, Attributes -AutoSize
Your output will be:
Name PSIsContainer LinkType Target Attributes
---- ------------- -------- ------ ----------
dir1 True {} Directory
file1 False HardLink {C:\linktest\hfile1} Archive
file2 False {} Archive
hfile1 False HardLink {C:\linktest\file1} Archive
jdir1 True Junction {C:\linktest\dir1} Directory, ReparsePoint
sdir1 True SymbolicLink {C:\linktest\dir1} Directory, ReparsePoint
sfile1 False SymbolicLink {C:\linktest\file1} Archive, ReparsePoint
Note that both file1 and hfile1 are hard links, even though file1 wasn't created as such.
To clean up the above garbage, do:
Get-ChildItem -Path C:\linktest\ | ForEach-Object { $_.Delete() }
There's a bug in Remove-Item with deleting some container links which prevents the command from removing the items.
The general solution would be to get the item and test it:
# Get the item. Don't use Get-ChildItem because that will get a directory's contents
$Item = Get-Item -Path $Path
# Is it a container
$Item.PSIsContainer
# Is it a link of some kind?
[System.String]::IsNullOrWhiteSpace($Item.LinkType)
$Item.LinkType -eq 'Junction'
# Is it a Reparse Point?
($Item.Attributes -band [System.IO.FileAttributes]::ReparsePoint) -eq [System.IO.FileAttributes]::ReparsePoint
There are several other potential attributes, too:
PS> [System.Enum]::GetNames([System.IO.FileAttributes])
ReadOnly
Hidden
System
Directory
Archive
Device
Normal
Temporary
SparseFile
ReparsePoint
Compressed
Offline
NotContentIndexed
Encrypted
IntegrityStream
NoScrubData
Note that Device is documented as reserved for future use. Ain't no device file type in Windows.
For volume mount points, I'm not 100% sure how those look. I know you can create them on Windows 8.1 and later with Get-Partition followed by an appropriate Add-PartitionAccessPath, but I'm on Windows 7 currently. I'm afraid I have no means of testing this at the moment.
Finally, I have no idea how exactly PowerShell Core 6.0 on Linux handles file types.
Soooo,,,,
This is not something I regulary do, but if memory serves. In *nix, a regular file contains data, is a direcotry,
Again, not somehting I do/have to worry about under normal PoSH stuff.
So you are testing for where the object is a writable file (and / or non-zero) or a directory or binary?
So, in PoSH, prior to v3... you do something like this...
$IsDir = {$_.PsIsContainer}
$IsFile = {!$_.PsIsContainer}
ls D:\Temp | Where $IsDir
lsectory: D:\Temp
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 1/4/2018 2:31 PM ArchiveDestination
d----- 1/4/2018 1:40 PM ArchiveSource
d----- 1/1/2018 3:34 PM diff
...
ls D:\Temp | Where $IsFile
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 6/7/2017 5:28 PM 512 CombinedSources07Jun2017.txt
-a---- 2/24/2018 6:29 PM 115 EmpData.csv
-a---- 11/18/2017 6:47 PM 11686 fsoVolume.docx
...
PoSH V3 and higher. This is supported natively e.g.:
ls -directory
ls -ad
ls -file
ls -af
Of course any of the above can be set to just return true or false using if/then or try/catch.
If all the above is a bit more typing than you'd like then you can create your own function and give it whatever alias you choose, well, as long as it's not an alias already in use.
See the help files ...
# Get parameters, examples, full and Online help for a cmdlet or function
(Get-Command -Name Get-ChildItem).Parameters
Get-help -Name Get-ChildItem -Examples
Get-help -Name Get-ChildItem -Full
Get-help -Name Get-ChildItem -Online
Get-Help about_*
Get-Help about_Functions
Get-Alias -Definition Get-ChildItem
# Find all cmdlets / functions with a target parameter
Get-Help * -Parameter Append
# All Help topics locations
explorer "$pshome\$($Host.CurrentCulture.Name)"
Of course you can check / modify file attributes as well. See this article on the topic:
File Attributes in PowerShell
Fun with file and folder attributes, via PowerShell and the DIR command.
https://mcpmag.com/articles/2012/03/20/powershell-dir-command-tricks.aspx
So, you could do something like this, to achieve the same attribute check
Get-ChildItem -Path $FilePath -File -Force | Where {$_.Attributes -notmatch 'ReadOnly'}
Or a function wiht an alias.
Function Test-RegularFile
{
[CmdletBinding()]
[Alias('trf')]
Param
(
[string]$FilePath
)
try
{
Get-ChildItem -Path $FilePath -File -Force `
| Where {$_.Attributes -notmatch 'ReadOnly'}
"$FilePath is a regular file" # success: regular file is readable
}
catch
{
Write-Warning -Message "$FilePath is not a Regular file."
}
}
trf -FilePath D:\Temp\fsoVolume.txt
Since you are new to PoSH, it reall important / vital that you get a base understanding before looking at conversion comparisons.
See this post for folks providing some paths for learning PowerShell.
https://www.reddit.com/r/PowerShell/comments/7oir35/help_with_teaching_others_powershell
To test whether it's a regular file:
Test-Path -PathType Leaf foo.txt
To test whether it's readable:
Get-ChildItem foo.txt | ? { $_.Mode -match 'r'}
To test whether it's hidden:
Get-ChildItem -force foo.txt | ? { $_.Mode -match 'h'}
I have a share with a file structue like so
Public ( no restrictions )
Sales ( only sales people have access )
Production ( Production only has access to this )
I created the permissions, but if someone creates a new folder in there, the permissions on that new folder is not the same as the parrent, Is there a way to force permissions ( or even a script I could run to re-set the permissions nightly )
This can be done through the GUI as a once off - click the Advanced button on the Security tab in the folder properties, and make you've disabled inheritance on your main sub folders, and then check to ensure any custom security settings apply to "this folder, sub folders and files". You may also need to check "replace all child object permissions ..." as well.
From the command prompt, you can use the command "icacls" which is really powerful and is what I tend to use when configuring permissions like this.
as u suggested, I wrote below script. Hope it could help
$folders = Get-ChildItem -Path $share -Directory
foreach ($folder in $folders)
{
$acl = Get-Acl $folder
Get-ChildItem $folder -Recurse | %{Set-Acl -Path $_.FullName -AclObject $acl}
}
I'm currently using Vista 32-bit. How do I add the Windows security group "Everyone" and give full control to a directory and all of it's sub-directories and all files? Is there a powershell script that I could use?
Thanks!
I've expanded on martona's snippet and was able to give access to all folders and sub-folders. Here's my code -
$FilesAndFolders = gci "c:\data" -recurse | % {$_.FullName}
foreach($FileAndFolder in $FilesAndFolders)
{
#using get-item instead because some of the folders have '[' or ']' character and Powershell throws exception trying to do a get-acl or set-acl on them.
$item = gi -literalpath $FileAndFolder
$acl = $item.GetAccessControl()
$permission = "Everyone","FullControl","Allow"
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission
$acl.SetAccessRule($rule)
$item.SetAccessControl($acl)
}
Sometimes the "native" PowerShell way isn't necessarily the best way. For something like this I would still use icacls.exe. Remember that good ol' exes work pretty good in PowerShell. Just cd to the directory you want to set and execute:
icacls $pwd /grant "Everyone":(OI)(CI)F
This will give Everyone full access to the current directory downwards (via permission inheritance). This should work as long as there are no explicit denials to Everyone in the dir structure.
$acl = Get-Acl c:\mydir
$permission = "Everyone","FullControl","Allow"
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission
$acl.SetAccessRule($rule)
$acl | Set-Acl c:\mydir