gab
gab

Reputation: 63

How to fix for /f loop in batch file to run multiple powershell scripts in directory

I am trying to make the following command run multiple powershell script files located in a specified directory:

@echo off
for /F %%f in ('dir /b "C:\ProgramData\MyScripts\"') do Powershell.exe -ExecutionPolicy Bypass -NoLogo -WindowStyle Hidden -File C:\ProgramData\Scripts\%%f
pause

It works fine in the command line, however it doesn't work in a batch file (even though the "%" has been changed to "%%"). Any ideas how I can make this work?

Upvotes: 2

Views: 1270

Answers (2)

Compo
Compo

Reputation: 38718

The following is a method I would suggest you try:

@If Exist "C:\ProgramData\MyScripts\*.ps1" For %%A In (
    "C:\ProgramData\MyScripts\*.ps1"
)Do @Powershell -NoP -NoL -Ex Bypass -W Hidden -F "C:\ProgramData\MyScripts\%%A"

I have filtered to ensure that only .ps1 files are parsed, to exclude any non PowerShell scripts from being run. I have also changed the location of the files to run, because it appeared that you were parsing files in one directory, C:\ProgramData\MyScripts, but trying to run them in another, C:\ProgramData\Scripts.

Note also that this will not run every file in the directory, those which are for instance hidden will not be parsed. To do that you'd be better advised to use a For /F loop and choose the files using the Dir command:

@For /F Delims^=^ EOL^= %%A In ('
    Dir /B/A-D-L "C:\ProgramData\MyScripts\*.ps1" 2^>Nul
')Do @Powershell -NoP -NoL -Ex Bypass -W Hidden -F "C:\ProgramData\MyScripts\%%A"

Please take account that each script will be run after the previous one has ended, if you wished to run each immediately after beginning the previous one, I'd suggest you open a Command Prompt window and take a look at the help information output from Start /?, for a method of doing so.

Upvotes: 1

mklement0
mklement0

Reputation: 440431

I suggest you restructure your approach so as to avoid having to duplicate the scripts' directory path - which may well be the source of your problem:

Let PowerShell do the file enumeration:

@echo off
powershell -ExecutionPolicy Bypass -WindowStyle Hidden -Command ^
  "dir C:\ProgramData\MyScripts\*.ps1 | foreach { & $_ }"
pause

Note that switching from -File to -Command was necessary in order to submit an entire PowerShell command; -NoLogo is then not needed.

Also consider adding -NoProfile to suppress loading of your profile file.

As for the PowerShell command:

  • dir is used for brevity, but note that it is an alias, namely for the Get-ChildItem command.
  • foreach is an alias for the ForEach-Object cmdlet, which runs the associated script block ({ ... }) for each input object (file), reflected in automatic variable $_.
  • & is the call operator, which is needed to invoke a command (name or path) stored in a variable.

If you prefer to stick with your original approach and want to fix that, see Compo's helpful answer.

Upvotes: 1

Related Questions