jammanX
jammanX

Reputation: 57

Preventing multiline command from being interpreted in batch file

I am trying to use the powershell command from here in a batch file. I want it to loop through a folder, printing each folder's name and size. What am I missing in my code from getting it to work?

I have tried using quotes all over the place. I have also tried using escape characters. Perhaps it's because I am new to writing batch files, but I can't figure it out.

@echo off

set "my_path=%~dp0"

set file_size_command=switch((ls -r|measure -s Length).Sum) {^
 {$_ -gt 1GB} {'{0:0.0} GiB' -f ($_/1GB)^
 break}^
 {$_ -gt 1MB} {'{0:0.0} MiB' -f ($_/1MB)^
 break}^
 {$_ -gt 1KB} {'{0:0.0} KiB' -f ($_/1KB)^
 break}^
 default { "$_ bytes" }^
 }

for /d %%a in ("%my_path%\*") do (
    echo Folder name: %%~nxa
    PowerShell.exe -noexit -command %file_size_command%
)

pause
rem Let the user view this

It's supposed to just print each folder's name and then the size of the folder. Currently, it interprets the {$_ as a command.

Upvotes: 2

Views: 68

Answers (1)

mklement0
mklement0

Reputation: 438093

The following should do what you want:

@echo off

set "my_path=%~dp0"

set file_size_command=^& { switch^(^(ls -r $args[0] ^|measure -s Length^).Sum^) {^
 {$_ -gt 1GB} {'{0:0.0} GiB' -f ^($_/1GB^)^
 ; break}^
 {$_ -gt 1MB} {'{0:0.0} MiB' -f ^($_/1MB^)^
 ; break}^
 {$_ -gt 1KB} {'{0:0.0} KiB' -f ^($_/1KB^)^
 ; break}^
 default { $_.ToString() + ' bytes' }^
 } }

for /d %%a in ("%my_path%\*") do (
    echo Folder name: %%~nxa
    PowerShell.exe -noprofile -command "%file_size_command%" "%%~fa"
)
  • All cmd.exe metacharacters - notably, ( ) & | - must be ^-escaped in the %file_size_command% variable value.

  • The ^ at end of a line is a line continuation that does not include the newline, so your break statements must be preceded by ; for the syntax to be valid.

  • Because the variable must later be passed with enclosing "...", it's easier to avoid " chars. in the variable value.

  • To pass each directory path as an argument to the PowerShell code, enclose the switch statement in & { ... }, which allows the switch statement to refer to it as $args[0].

Upvotes: 3

Related Questions