Use PowerShell to clear stubborn file attributes

For several years we’ve used a basic data backup program that exploits the archive bit on files to determine if they need to be backed up or not. We run a weekly full backup with daily differentials. After the weekly backup is run, the archive bit is reset on all files, ready for the next week.

Except it isn’t.

It turns out that if the file has both the system and hidden bit set, you can’t change any of the attributes. This is apparently a known issue that goes right back to the attrib command back in the MS-DOS days.

The end result is that our differential backups end up full of seemingly empty directories that simply don’t need to be there. The usual culprit is a hidden desktop.ini or thumbs.db file.

The simple solution would of course be to run the attrib -a /s /d command on the drive after the weekly backup has completed. But as we now know, that doesn’t work:

PowerShell to the Rescue!


Here are two helpful PowerShell commands. The first can be used to reveal files with their archive bit set, prior to you clearing it.

Find Files to Archive

Use this command to find all files with the Archive bit set. Delete “-recurse” if you DON’T want it to look into sub-folders.

Get-ChildItem <Drive\Folder\File> -recurse -force | where {(Get-ItemProperty $_.fullname).attributes -BAND [io.fileattributes]::archive}

Clear the Archive Bit

Here’s a so-called one-liner that will do the job:

Get-ChildItem <Drive\Folder\File> -recurse -force | foreach {Set-ItemProperty -path $_.FullName -Name attributes -value ((Get-ItemProperty $_.fullname).attributes -BAND ([io.fileattributes]::hidden + [io.fileattributes]::readonly) + [io.fileattributes]::normal + [io.fileattributes]::system) }

Here’s what it’s doing, step by step:

Get-ChildItem <Drive\Folder\File> -recurse -force |
foreach {Set-ItemProperty -path $_.FullName -Name attributes -value 
((Get-ItemProperty $_.fullname).attributes -BAND ([io.fileattributes]::hidden + [io.fileattributes]::readonly) + [io.fileattributes]::normal + [io.fileattributes]::system) }
  1. Return all the files in the nominated path, even the hidden ones
  2. For each file, we’ll set its ‘attributes’ property with a value of…
  3. the result of a Binary AND (‘BAND’) of the file’s current attributes, and a grouping of all the writeable attributes permitted – EXCEPT for Archive.

The end result of the final step – the AND – is that if any of the other attributes (System, Normal, ReadOnly and Hidden) are present, they’ll be retained, but if Archive is set it will be dropped.

As always, re-run the ‘find files’ commandlet upon completion to confirm the outcome is as expected.

References

Thank you Scripting Guy Ed Wilson: Use PowerShell to Toggle the Archive Bit on Files.

Revision History

6th October 2020. This is the initial publication.
 
– G.

6 Comments

  1. I actually used your tip to fix a bug with my clouder server (HiDrive) where files with a “Temporary” attribute set by an app I use daily couldn’t be synchronised with the app. So I added the Archive attribute to it and voila!

    Get-ChildItem -recurse -force | foreach {Set-ItemProperty -path $_.FullName -Name attributes -value ((Get-ItemProperty $_.fullname).attributes -BAND ([io.fileattributes]::hidden + [io.fileattributes]::readonly) + [io.fileattributes]::archive) + [io.fileattributes]::normal + [io.fileattributes]::system) }

  2. Every file is in error. I’ve run it in admin and standard modes it made no difference. I also ran it using just a path (c:\) and a path + wildcard (c:\*.*).

    Set-ItemProperty : Exception setting “Attributes”: “Access to the path is denied.”
    At line:1 char:49
    + … | foreach {Set-ItemProperty -path $_.FullName -Name attributes -valu …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Set-ItemProperty], SetValueInvocationException
    + FullyQualifiedErrorId : CatchFromBaseAdapterSetValue,Microsoft.PowerShell.Commands.SetItemPropertyCommand

  3. Hi Greig;

    I tried 3 different ways one under my regular elevated admin account and the other logging in directly admin.

    I already had the script setup to run as a scheduled task running as System and using the highest priviledges both failed. Running under my admin user account I got the same errors as I did initially. But running using the actual admin account I got a similar error but it looks very different and I’m not sure why.

    This error looks different depending what account I’m on. Maybe a setup issue with Notepad++? Is it codepages I think they used to call them? It seems to have ANSII encoding for some reason.

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~[0m
    [31;1m[0m[36;1m[36;1m[0m[36;1m[0m[36;1m[31;1m[31;1m[36;1m | [31;1mException setting “Attributes”: “Access to the path ‘C:\Program Files\Common Files\microsoft[0m
    [31;1m[0m[36;1m[36;1m[0m[36;1m[0m[36;1m[31;1m[31;1m[36;1m[31;1m[36;1m | [31;1mshared\ink\ar-SA\tipresx.dll.mui’ is denied.”[0m
    [31;1mSet-ItemProperty: [0mE:\SharedData\PowershellScripts\ArchiveAttributeUpdate.ps1:2[0m
    [31;1m[0m[36;1mLine |[0m
    [31;1m[0m[36;1m[36;1m 2 | [0m . | foreach {[36;1mSet-ItemProperty -path $_.FullName -Name attributes -valu[0m .[0m
    [31;1m[0m[36;1m[36;1m[0m[36;1m[0m[36;1m | [31;1m

    The actual file that failed tipresx.dll.mui
    and it’s folder security:

    “Path”
    “C:\Program Files\Common Files\microsoft shared\ink\ar-SA”

    “Read”
    “Administrators, APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES, APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES, Users”

    “Write”
    “Administrators” “”

    Then I saw that Administrators were the only ones with write access and I took the script line and copied it to CMD just logged in as the system admin and tried to run it but the same thing again.

    File Security

    Owner TrustedInstaller

    Allowed
    Principals Access
    TrustedInstaller Full
    Administrators R&E
    System R&E
    Users R&E
    All Application Packages R&E
    All Restricted Application Packages R&E

    I tried to figure out a way to run as TrustedInstaller but had no success.

    • > This error looks different depending what account I’m on. Maybe a setup issue with Notepad++?

      I’ve never seen something like that. To prove it one way or another, just change the encoding in NP++: Encoding / Convert to UTF-8.

      But if Admins can only read & execute but not write, there’s why it won’t let you change the attributes.

      What’s your goal here anyway?

      • I don’t want to create unnecessary backups. I have a lot of large mostly static drives that don’t need backed up unless they change but the software isn’t able to set the attributes that it seems to rely on to make the determination.

        I didn’t set the security that’s how Window’s is installed. I know from messing with TrustedInstaller in the past it’s finicky and from a security point it makes sense to not allow admins or system to have full control but if there’s no overrides as we’ve been taught, Admin usually has total access to everything, what is the point of admin authority? Anything using attributes as a control is wrong at least on the system drive. Plus there’s the whole ownership issue.

        I don’t know the rules of how the attribute gets set or unset but I know it’s not dependible because it’s not getting set and unset and I cannot seem to affect that by the attrib command because of the security. When I read about Task Scheduler and it’s ability to use the highest security level and setting the user that runs the task I thought for sure this must work because it’s under control of the system and is supposedly isolated from any “corruption” per MS yet even this can’t get around the system security. A hacker could probably do it in an afternoon.

        I guess I have to do the following:
        1. See if I’m able to affect other drives.
        2. Figure out if the system iternally is capable of setting and unsetting attributes and exploit how it accomplishes the task which would most likely work hand-in-hand with modified date. I don’t think it is at least not on the system drive.
        3. Maybe consider an exception on the system drive and just let it backup? More than likely there’s going to be changes from updates. Maybe there’s a single control file that would tell me if changes have been made?
        4. Figure out the existing security to see if adding system or admin as a full rights user on the system is a solution? Can I leave it or must I remove it? Can I create a TrustedInstaller group or another account that would have equal access that I could “runas”?
        5. What about drive level security does that also need to be changed?
        6. Do I need the owner to be something other than TrustedInstaller? If I change this I know in the past I’ve had to revert the security back or other processes start breaking down.

Leave a Reply to CityguyUSA Cancel reply

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

... and please just confirm for me that you're not a bot first: Time limit is exhausted. Please reload the CAPTCHA.

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