Avatar of ITPro44
ITPro44Flag for United States of America

asked on 

Convert old Scipt to Powershell

We have the following script that was written several years ago.  The purpose of this script is to change the permissions of all .JPG files within a directory and then change the file attribute to "A" so that it doesn't need to process these JPG's again.  However, because it's running on such a large amount of data, it takes over a week to run when all JPG's need to be processed.  I need to find a faster way to accomplish this task, but need assistance as I'm not an expert at scripting.  I thought converting this script to run in powershell would be ideal.  Can anyone assist me with this by re-writing this script in powershell?

@echo on
for /F "delims=*" %%F in ('xcopy /S /L "E:\DATA\*.jpg" \ ^| findstr /v File^(s^)') do (
  xcacls "%%F" /P "Authenticated Users:R" "Domain\Administrator:F" "SYSTEM:F" "Photo Admins:F" /Y
  attrib -a "%%F"
)

Open in new window

PowershellScripting LanguagesWindows BatchSystem ProgrammingVB Script

Avatar of undefined
Last Comment
ITPro44
Avatar of Qlemo
Qlemo
Flag of Germany image

I doubt you can speed up the overall process.
Instead of XCopy and findstr, I would use dir /a:-a /s /b E:\DATA\*.jpg - but don't think that is faster.

In PowerShell the only pro is that the files get processed as soon as they are seen in the directory. The batch file above has first to process the complete directory, and then applies changes. This is not faster, but allows the process to get interrupted at any point, and restarting should be reasonable fast.
Avatar of arnold
arnold
Flag of United States of America image

Any reason why the settings is not applied once to the e:\Data\ directory or is the issue that files end up without inherit rights?

http://blogs.technet.com/b/heyscriptingguy/archive/2014/02/03/list-files-in-folders-and-subfolders-with-powershell.aspx
Avatar of zalazar
zalazar

I agree with Qlemo as I also think that converting it to the same code with PowerShell won't help you that much. This since the script is processing each file one by one which is slowing down the process very much. Maybe another tool then xcacls can update the permissions a bit faster but the better optimization would be to rewrite the script in a way that multiple threads of xcacls will be started at the same time.
Avatar of ITPro44
ITPro44
Flag of United States of America image

ASKER

I know robocopy can be multithreaded by using the /MT switch.  Could robocopy be utilized for this?
Avatar of zalazar
zalazar

Yes that's correct. Unfortunately robocopy can only copy NTFS permissions of files and dirs but it cannot change NTFS permissions of an existing file so you can't use it for this task.
I can try to look into a faster way of doing this task but it will cost some time to sort out.
Avatar of arnold
arnold
Flag of United States of America image

you could but xcopy and robocopy using the /L flag are only there to enumerate the files in the source matching a criteria.

What is the issue that prompted the need for setting these rights individually on the file, that setting on the entire directory will not work?
A better option since you are concerned with images, is to separate the images ...

Context for this setup may explain, i.e. you would like to grant additional rights to a group of people but only to a subset of files.

Note that this script keeps updating the same files everytime it runs.
using powershell, you would/should narrow the searc criteria to include recently created/modified files

a unix utility find will do the search/listing including

powershell, fileobject, and foreach you can then set the permissions within without the need to call xcacls ......
Avatar of ITPro44
ITPro44
Flag of United States of America image

ASKER

Unfortunately, we can't separate out the JPG's from the other files and this is why we can't set permissions on the top level folder.
Avatar of ITPro44
ITPro44
Flag of United States of America image

ASKER

My reason I mentioned robocopy is that I thought it would speed up the 1st stage of the process which is to gather a list of all file names that need to be processed.  Will it not do that?
Avatar of Qlemo
Qlemo
Flag of Germany image

No.
Avatar of ITPro44
ITPro44
Flag of United States of America image

ASKER

Qlemo - can you provide me with the script that would use "dir /a:-a /s /b E:\DATA\*.jpg" instead of xcopy and fidstr, as you suggested?  I'll give this a try.
Avatar of ITPro44
ITPro44
Flag of United States of America image

ASKER

zalazar - please do let me know if your able to find an alternative way that would make this faster.
Avatar of zalazar
zalazar

Sure, I will let you know.
Avatar of Qlemo
Qlemo
Flag of Germany image

@echo on
for /F "delims=*" %%F in ('dir /a:a /s /b E:\DATA\*.jpg') do (
  xcacls "%%F" /P "Authenticated Users:R" "Domain\Administrator:F" "SYSTEM:F" "Photo Admins:F" /Y
  attrib -a "%%F"
)

Open in new window

The dir I provided originally was wrong. it listed all files having the archive attribute NOT set.

The PowerShell way is something like this, in case you want to test:
Get-ChildItem E:\Data -include *.jpg |
  ? { $_.Attributes -band [System.IO.FileAttributes]::Archive } |
  % {
    xcacls "$_.FullName" /P "Authenticated Users:R" "Domain\Administrator:F" "SYSTEM:F" "Photo Admins:F" /Y
    $_.Attributes = $_.Attributes -bxor [System.IO.FileAttributes]::Archive
  }

Open in new window

As you can see, it is not really different, processing is very similar. The full .NET method to replace xcacls is more complex, and would not help to change speed either, so I just left the command.
Avatar of ITPro44
ITPro44
Flag of United States of America image

ASKER

Thanks Qlemo - for the first script, when I run it, get the following error.  

xcacls "E:\DATA\IMG_0001.JPG" /P "Authenticated Users:R" "Domain\Administrator:F" "SYSTEM:F" "Photo Admins:F" /Y
 attrib -a "E:\DATA\IMG_0001.JPG"
)
ERROR: No mapping between account names and security IDs was done.

Open in new window


For the second powershell script, I copied it into a text file and gave it a PS1 extension name.  I then tried to run it in powershell by cd'ing into the directory of the file and then calling by using ".\text4.ps1"  I immediately get the following result.  Nothing was run or changed on the data :

PS C:\IT\SCRIPTS> ".\test3.ps1"
.\test3.ps1
PS C:\IT\SCRIPTS>

Open in new window


What do you suggest?
Avatar of Qlemo
Qlemo
Flag of Germany image

Try the listed xcacls line as shown in the error message again (outside of the batch). It should report the same error, which tells that there is a unknown group or user provided.

The PS1 file did not run because of the double quotes - that results in a string. Remove the double quotes, or use the "exec" operator &:
.\test.ps1
& ".\test.ps1"
& '.\test.ps1'

Open in new window

Avatar of ITPro44
ITPro44
Flag of United States of America image

ASKER

I removed the double quotes and it still doesn't run.  I get this result instead.

PS C:\IT\SCRIPTS> .\test3.ps1
PS C:\IT\SCRIPTS>

Open in new window


My mistake on the xcacls error - that has been resolved.  thank you.
Avatar of Qlemo
Qlemo
Flag of Germany image

Oops, forget to iterate thru subfolders. Shame on me.
Get-ChildItem E:\Data -include *.jpg -recurse |
  ? { $_.Attributes -band [System.IO.FileAttributes]::Archive } |
  % {
    xcacls "$_.FullName" /P "Authenticated Users:R" "Domain\Administrator:F" "SYSTEM:F" "Photo Admins:F" /Y
    $_.Attributes = $_.Attributes -bxor [System.IO.FileAttributes]::Archive
  }

Open in new window

Avatar of ITPro44
ITPro44
Flag of United States of America image

ASKER

I now get another error using the update script.  The script changes the archive attribute from "A" to "N" but does not change any permissions on the files:

PS C:\IT\SCRIPTS> .\test3.ps1
ERROR: The system cannot find the file specified.
ERROR: The system cannot find the file specified.
ERROR: The system cannot find the file specified.
ERROR: The system cannot find the file specified.
ERROR: The system cannot find the file specified.
ERROR: The system cannot find the file specified.
ERROR: The system cannot find the file specified.
ERROR: The system cannot find the file specified.
ERROR: The system cannot find the file specified.
ERROR: The system cannot find the file specified.
ERROR: The system cannot find the file specified.
PS C:\IT\SCRIPTS>

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Qlemo
Qlemo
Flag of Germany image

Blurred text
THIS SOLUTION IS ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
Avatar of ITPro44
ITPro44
Flag of United States of America image

ASKER

It now changes the archive attribute from A to N but does not change the permissions.  It gives the following error:

PS C:\IT\SCRIPTS> .\test3.ps1
ERROR: No mapping between account names and security IDs was done.
PS C:\IT\SCRIPTS>

Open in new window

Avatar of Qlemo
Qlemo
Flag of Germany image

Did you apply the same correction as stated in http:#a40880250 ? The batch file had the same issue.
Avatar of ITPro44
ITPro44
Flag of United States of America image

ASKER

I did, however, I failed to save the changes.  My mistake.  It's working now.  

This script above only processes files with the Attribute set to "A".  Is the script below the proper way to process all .JPG files no matter if the attribute is "A" or "N"?

Get-ChildItem E:\Data -include *.jpg -recurse |
  % {
    xcacls "$($_.FullName)" /P "Authenticated Users:R" "Domain\Administrator:F" "SYSTEM:F" "Photo Admins:F" /Y
    $_.Attributes = $_.Attributes -bxor [System.IO.FileAttributes]::Archive
  }

Open in new window

Avatar of Qlemo
Qlemo
Flag of Germany image

Yes.
Avatar of ITPro44
ITPro44
Flag of United States of America image

ASKER

great, thanks.  I like that this powershell script identifies and processes each file in one swoop.

One other question I have - I currently don't have a way for this script to notify me if an error occurs.  Do have any suggestions?
Avatar of Qlemo
Qlemo
Flag of Germany image

Since this code is using a mixture of external and internal commands, logging is a bit more demanding. I assume you've stored the code in a script file, and run it from PowerShell prompt. Then something like
  .\script.ps1 > log.txt 2>&1
will log both success and error messages, as you would see them on the screen (without colour, of course)
Avatar of ITPro44
ITPro44
Flag of United States of America image

ASKER

I'd like to have an email generated that will send the job status (success or error) with the log attached.  Is this possible?  Perhaps I should create another question for this.  Let me know if that is the best route.
Avatar of Qlemo
Qlemo
Flag of Germany image

That's a different question, and a more difficult one. Sending a mail is easy, but detecting success and failure needs some work.
Avatar of ITPro44
ITPro44
Flag of United States of America image

ASKER

Thanks for all the help.  I'll create a new question for this.
System Programming
System Programming

Kernel and system programming is the process of creating the software necessary for a computer or device to function and operate other programs. Some operating systems (such as Microsoft Windows) are proprietary, but others, such as the various Linux distributions, are open source.

41K
Questions
--
Followers
--
Top Experts
Get a personalized solution from industry experts
Ask the experts
Read over 600 more reviews

TRUSTED BY

IBM logoIntel logoMicrosoft logoUbisoft logoSAP logo
Qualcomm logoCitrix Systems logoWorkday logoErnst & Young logo
High performer badgeUsers love us badge
LinkedIn logoFacebook logoX logoInstagram logoTikTok logoYouTube logo