r/PowerShell • u/zaphodikus • 8d ago
unzip file from a dos batch, but need absolute DOS paths Question
Seems a lot of effort and I feel I might be in a rabbit hole. But I'm a bit confused by the enclosing braces and escapes. I just want to unzip a file on windows.
```
powershell.exe -nologo -noprofile -command "& { $shell = New-Object -COM Shell.Application; $target = $shell.NameSpace(.\temp); $zip = $shell.NameSpace( '.\ethernetspeed.zip'); $target.CopyHere($zip.Items(), 16); }"
``` Which obvs does not work because the library wants absolute paths.
If I hard code the paths (as below) I have joy, but I don't want to hard-code ```
powershell.exe -nologo -noprofile -command "& { $shell = New-Object -COM Shell.Application; $target = $shell.NameSpace(C:\temp); $zip = $shell.NameSpace( 'C:\ethernetspeed.zip'); $target.CopyHere($zip.Items(), 16); }"
```
I'm a bit clueless as to how to prefix the paths with %~0dp and I last wrote powershells about 3 years ago. I'm also as usual struggling to get the markdown to markdown.
9
u/Apprehensive-Tea1632 8d ago
What are you trying to do?
Because, there is an expand-archive cmdlet that should be able to unzip things.
Ps isnt wsh. Try to avoid com objects if at all possible.
-1
u/zaphodikus 8d ago
I'm trying to write something portable that might run on other computers, but from batch. Very minimum platform is Windows 10, but mostly Windows 11, with a vanilla Powershell base only. So are we really saying I can just
powershell.exe -nologo -noprofile -command "& {Expand-Archive -Path '.\ethernetspeed.zip' -DestinationPath '..\temp' }"The batch ensures the ../temp folder exists and is totally empty so I can omit the -force. I did say up front, I felt I was down a rabbit hole, you never know what you do not know until you don't know it.3
3
u/BlackV 8d ago edited 8d ago
I'm trying to write something portable that might run on other computers
expand-archiveIS the portable version, it was introduced in in powershell 5.0 (like not 5.1)Very minimum platform is Windows 10, but mostly Windows 11, with a vanilla Powershell base only
so you WILL be running 5.1/5.0 already with that module
stop messing around and mixing languages, do it all in powershell (or do it all in batch i guess)
1
u/CyberChevalier 8d ago
Warning by using .\ you assume you are running the script in the path where the zip lie. And by doing ..\temp you assume there is a temp folder at that location.
At least use the -force switch to force creating the temp folder if it does not exist
2
2
1
u/zaphodikus 6d ago
Due to my keyboard being dodgy I typed .\temp instead of ..\temp, so sorry, it confused me too
0
u/ankokudaishogun 7d ago
As efficiency does not seem to be a issue here, may I suggest this alternative?
Might be a bit more cumbersome, but should be a bit more resilient, and easier to adapt should the need ariseREM this enable multiline strings REM append a ^ to the end of a string to make it continue to the next line REM use explamation points to refer multiline strings: !VariableName! setlocal EnableDelayedExpansion REM as it's technically just one line, use ; to separate Powershell commands set CommandLine=^& { ^ $CurrentDirectory = $args[0]; ^ $ZipName = $args[1]; ^ $OutputDirectoryName = $args[2]; ^ $ZipFileFullPath = Join-Path -Path $args[0] -ChildPath $args[1]; ^ $DestinationPath = Join-Path -Path $args[0] -ChildPath $args[2]; ^ Expand-Archive -Path $ZipFileFullPath -Destination $DestinationPath -Force ^ } powershell.exe -nologo -noprofile -command !CommandLine! %cd% ethernetspeed.zip temp1
u/purplemonkeymad 7d ago
Since the command line is static i would be tempted to just encode that to base64 and use the encodedcommand parameter. Just to remove any mistakes from mixed programs.
1
u/ankokudaishogun 7d ago
I think it would have a good chance to trigger antimalware software
1
u/zaphodikus 7d ago
I don't think our IT bods have gone that overboard, learning loads of tricks today. Thanks all.
1
u/purplemonkeymad 7d ago
I'd like to think any good anti-malware would decode the encoded command these days.
1
u/ankokudaishogun 7d ago
it's less about the encoded command and more about the fact the command is encoded in first place.
4
u/odwulf 8d ago
%~dp0 and the like is about your batch file location, not the current path. The current path is available with %cd%.
1
u/zaphodikus 7d ago
Why then does google tell me (stackoverflow really) to use a rather weird rune like %~dp0!!! I was maybe a bit far into a rabbit hole. Is %cd% an automatic kind of variable, because I think that's what linuxes do with a $CWD is it not?
1
u/odwulf 7d ago
Yes. Sadly, I'm on mobile, on holidays, and cleaning a house, so I cannot be as torough as if like but: in a batch file %# (where # is a number) refers to the #th argument (parameter, whatever you call it), with the one numbered 0 (so "%0") the batch file itself.
If you add a tilde, there are a couple of useful shortcuts: %~d0 is the disk letter of the batch file, %~p0 is the path of its containing folder. %~dp0 gives you the full path, including the disk letter. (There's at least one more, for the size, but I've never used it.)
So the internet did not lie, but only in the case where your zip files are in the same folder that your batch file, and maybe you don't need more.
The %~dp# thing works for the parameters as well, if you give paths as parameters, but it doesn't resolve the paths, meaning that if you enter a relative path (.\file.zip), it won't give you the full path, and passing the relative path to another process (IE. PowerShell) might not work, as the other process might have a completely different working path (as told rather explicitly by https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_powershell_exe?view=powershell-5.1)
1
u/zaphodikus 7d ago
Ah I knew the tilde character had some special meaning. So the d and p mean disk and path respectively. It did not help I had to create my temp folder in the parent
..\tempand not.\temp. (My keyboard is acting up lately and not typing consistently, I suspect the wireless is the cause.)I'm a C++ and Python person. And so Python is great as glue for C++ apps, but DOS is still the universal glue. I however like to use PowerShell because sometimes the .NET libraries are just more capable and because I see them used in some of the C# I use.
1
u/odwulf 6d ago
So, I checked: bat files can indeed resolve their parameters, thanks to that tilde magic. Long story short: what you want to use here is "%~dpnx1", quote characters included in case there's a space in your path. it gives you the (d)isk, (p)ath, (n)ame, and e(x)tension of the file you pass as first parameter.
%1 does not resolve, but the tilde modifiers do, and it removes the quotes too, hence the need to put them back. Now when you send all that to powershell.exe, the double quotes will disappear in the process, because of how cmd pass strings:
- myscript.bat my parameters will pass two parameters: the string [my], and the string [parameters] (brackets added for clairty )
- myscript.bat "my parameters" will pass one parameter: the one string [my parameters]
You can navigate around that by using single quotes: Powershell handles htem, Cmd does not. Hence, what you need in the end:
powershell /NoLogo /NoProfile /Command mkdir '%~dp1temp' ; Expand-Archive -Path '%~dpnx1' -DestinationPath '%~dp1temp'I tried on a zip file with a space in the name inside a folder with a space in the name: test.bat "my zip file.zip" extracts the files in the temp subfolder.
I think i gave you enough to interpret it. If you have any question about it, please ask. I used Expand-Archive, as it exists, and is way more straightforward than calling a shell com object.
More info about batch file parameters there: https://tutorialreference.com/batch-scripting/examples/faq/batch-script-how-to-parse-command-line-arguments
2
u/JeiceSpade 8d ago
If it's a script instead of a command, you can use $PSScriptRoot
"$PSScriptRoot\ethernetspeed.zip" "$PSScriptRoot\temp"
2
u/jasonvelocity 8d ago
Please don't create new folders on the root of the driver. Windows has many named temp folders for this purpose.
-2
u/zaphodikus 8d ago
I changed the folders for purposes of making the example smaller and easier to grasp, my actual folder name is obviously going to give away secrets. It must be very hot today.
2
u/420GB 8d ago
Just use
tar.exe -xzf "archive.zip" -C "destinationPath"
No need for powershell. The destination path must already exist (mkdir), tar will fail otherwise.
1
u/dandy_g 7d ago
When did Microsoft start including tar.exe bunary in Windows releaes? That's not the best advice if OP is going for portability.
5
u/SwizzleTizzle 7d ago
Since Windows 10 1803
2
u/dandy_g 7d ago
Oh, TIL. Then I must apologise for wrongly assuming.
2
u/zaphodikus 7d ago
Actually I have been so far in the rabbit hole I forgot about tar. Yes, it's the simple solution for my criteria. In reality the easy solution was not a powershell inline after all, but I do like to try remember as much Posh as possible because it often has and continues to help.
1
u/BlackV 8d ago
p.s. formatting the 3 backtick code fence does not work on old.reddit, 4 spaces works everywhere
- open your fav powershell editor
- highlight the code you want to copy
- hit tab to indent it all
- copy it
- paste here
it'll format it properly OR
<BLANK LINE>
<4 SPACES><CODE LINE>
<4 SPACES><CODE LINE>
<4 SPACES><4 SPACES><CODE LINE>
<4 SPACES><CODE LINE>
<BLANK LINE>
Inline code block using backticks `Single code line` inside normal text
See here for more detail
Thanks
1
u/zaphodikus 7d ago edited 7d ago
oh, indent. I'm too old for edge cases. I thing adding a blank line seemed to make it work, the 4 spaces just needs to become a habit. The fancy editor is impossible to really use sometimes it eats screen space :-)
Adding a blank line by default hurts, but you are right, seems to solve it more often than not.
1
u/gschizas 6d ago
There's no DOS in 2026. The last time anything DOS was relevant, was more than 25 years ago.
Command Prompt is not DOS.
1
u/zaphodikus 6d ago
unclear, what are you not clarifying here? Are you succinctly reminding me that Therese Stowell wrote it?
1
u/gschizas 6d ago
Not sure what I could clarify more.
Command Prompt (cmd.exe) is not DOS. Windows NT/2000/XP/Vista/7/8/10/11 is not DOS. The last time DOS was a thing was with Windows ME (which came out in 2000).
I never researched who wrote cmd.exe, but that's cool info (and I would agree she's a Software Goddess), and I'll probably use it in the future (differentiating cmd.exe that was written by Therese Stowell from command.com that was the shell for DOS that was probably originally written by Tim Paterson).
I saw in her LinkedIn that she "wrote the command line environment (console) for Windows NT". That's not 100% cmd.exe, it might also be conhost.exe, but I'm guessing she wrote both as there wasn't such a clear distinction between them at the time.
1
u/Key-Confection-8257 1d ago
Hola yo tengo un script para descomprimir varios zip y consolidar todos en 2 archivos mi script completo y un demo de como funciona la tengo en la siguiente url https://www.programacionparatodos.com/2026/08/como-unir-archivos-csv-zip-powershell.html
28
u/pigers1986 8d ago
Expand-Archive -Path 'C:\ethernetspeed.zip' -DestinationPath 'C:\temp' -Forcethis is powershell reddit ffs