WIndows Command For-loop

for /f "delims=*" %f in ('dir "C:\folder\of\files\*.efs" /b') DO C:\folder\of\executable\program.exe -f "C:%~pf%f"
  1. A standard debugging technique is to insert the echo command into scripts and even compound/complex commands.  If you do
    for /f "delims=*" %a in ('dir *.avi /b /s') do @echo md "%~na"

    you’ll get the output

    "file 1"
    "file 2"
    "file 3"
    "file 4"


    • The @ prevents the echo commands themselves from displaying, so you see only their output.
    • "delims=…" tells for how to parse the lines of output from the dir *.avi /b /s command.  I don’t know why the answer you linked to suggests "delims=*".  But the default behavior is to break lines apart at spaces, so, if your directory and/or file names contain spaces (as you indicated), you should use "delims=" (specifying that there are no delimiters) to get this to work.
  2. If you type for /? or help for, you’ll get documentation on the for command.  Down in the fifth page, you’ll see
    In addition, substitution of FOR variable references has been enhanced.
    You can now use the following optional syntax:
        %~I         - expands %I removing any surrounding quotes (")
        %~pI        - expands %I to a path only
        %~nI        - expands %I to a file name only
    The modifiers can be combined to get compound results …

    which explains why %~na is getting you just the file name of the *.avi files whose full names are in %a.  Now try

    for /f "delims=" %a in ('dir *.avi /b /s') do @echo md "%~pa"

    and you’ll get

    "the_current_directory\Folder A\"
    "the_current_directory\Folder A\"
    "the_current_directory\Folder B\"
    "the_current_directory\Folder B\"

    From which we can conclude that you want to do

    for /f "delims=" %a in ('dir *.avi /b /s') do md "%~pa%~na"

    to create the file 1 and file 2 directories under Folder A, and the file 3 and file 4 directories under Folder B.   And, as @dave_thompson_085 points out, you can combine %~pa%~na into %~pna.

Powershell Query – get-ADObject filter for Bitlocker

The following command returns all objects in the specified OU (replace XXX with your own values) which have Bitlocker recovery information and what the recovery key is.

Get-ADObject -Filter "objectClass -eq 'msFVE-RecoveryInformation'" -SearchBase "OU=XXX, OU=XXX, OU=XXX, DC=XXX, DC=XXX, DC=XXX, DC=XXX" -Properties msFVE-RecoveryPassword,whenCreated

I’m only really interested in the machine name for review so the following command both chops the Distinguished name field and returns just the second part and then chops that part removing the “CN=” section whilst also returning just that column name from the above query.

Get-ADObject -Filter "objectClass -eq 'msFVE-RecoveryInformation'" -SearchBase "OU=XXX, OU=XXX, OU=XXX, DC=XXX, DC=XXX, DC=XXX, DC=XXX" | Select @{l='ComputerName';e={$_.DistinguishedName.split(',')[1].split('=')[1]}}

The tricky part was the select statement, here’s a brief breakdown of what it’s doing.

@{} defines an array to be returned, which we’ll expect although it could end up being an array of 1 or 0 with no results.

“l” is shorthand for “label” which is the column header.
“e” is shorthand for “expression”.
“$_.” indicates a single item in the pipeline, the results of Get-ADObject are then piped and this catches them one at a time.
“DistinguishedName.split(‘,’)[1].split(‘=’)[1]” takes the value of the name DistinguishedName being piped and splits it first by “,”, selecting the second item in the array that forms “[1]” is second when counting from 0. It then splits that string again on the “=” sign, returning the second part (the actual computer name alone!).



Learned a little more, powershell syntax understanding on the up!