Jump to content

Possible to do this Batch without using a temporary file?


Recommended Posts

I have a batch routine that works very well, but I thought it might be improved to not use a temporary file at all -- less wear and tear on SSDs etc.

What I'm doing is checking a directory for the existence of files, not folders, and if found then proceed. Here is what currently works:

...
(SET "_Dir1=%~1") & IF DEFINED _Dir1 (SET "_Dir2=!_Dir1!\") ELSE (SET "_Dir2=")
DIR /-B/O-N/A-D "!_Dir1!">md5.tmp 2>nul
SET /P _FirstLine=<md5.tmp
del md5.tmp >nul 2>&1
IF DEFINED _FirstLine ...
...

Any ideas on how to not need a temporary file? I don't care at all what the file is, I just need to know if a file, not folder, is present.

EDIT:
I still want the answer to the above, if there is one, but I will also admit that step might not even be strictly necessary. I'm sometimes guilty of the belt + suspenders approach to coding.

Here is the follow on code.:

...
IF DEFINED _FirstLine (FOR /F "tokens=*" %%G IN ('dir /-B/O-N/A-D "!_Dir1!"') DO IF /i NOT "%%G"=="App.md5" md5sum "!_Dir2!%%G">>App.md5)
...

I just wanted to make absolutely sure that the command [ md5sum "!_Dir2!%%G">>App.md5) ] was not run unless there was a file to run it against. This isn't the only time that command is run, but rather I recurse through the directory structure and I didn't want there to be any chance of garbage of any kind ending up in App.md5, not even empty lines.

To be thorough, here is the entire function:

:f_RecurseMd5 %_DirNames%
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
(SET "_Dir1=%~1") & IF DEFINED _Dir1 (SET "_Dir2=!_Dir1!\") ELSE (SET "_Dir2=")
(DIR /-B/O-N/A-D "!_Dir1!">md5.tmp 2>nul) & (SET /P _FirstLine=<md5.tmp) & (del md5.tmp >nul 2>&1)
IF DEFINED _FirstLine (FOR /F "tokens=*" %%G IN ('dir /-B/O-N/A-D "!_Dir1!"') DO IF /i NOT "%%G"=="App.md5" md5sum "!_Dir2!%%G">>App.md5)
FOR /F "tokens=*" %%G IN ('dir /-B /AD "!_Dir1!"') DO IF EXIST "!_Dir2!%%G" (CALL :f_RecurseMd5 "!_Dir2!%%G")
:f_CleanUp
FOR /F "tokens=1* delims==" %%G IN ('"SET "_" 2>nul"') DO (SET "%%G=") & ENDLOCAL&EXIT /B 0

...which can be called either while already in the directory you want to examine ( so no argument is passed ), or pointing to the directory you want to examine.

Thanks in advance.

Cheers and Regards

Edited by bphlpt
added further explanation
Link to comment
Share on other sites


29 minutes ago, bphlpt said:

No suggestions?

Cheers and Regards

Some. :dubbio:

 "md5sum" is not a built-in batch command, so it must be an external program (and as such it should be always invoked as md5sum.exe, possibly even including its path to avoid possible issues when the batch is moved.

This said, I would personally rather avoid the IF check and rather use a pipe to FIND,

Also - surely you have your reasons but the /o-n parameter to dir doesn't seem like *needed*.

As well, you surely have your reasons, but usually the setlocal is done globally on the whole batch and not within a function/subroutine, and without other information the EXIT /B seems superfluous.

For the record, a directory should always ends with \.

Anyway, provided that I got the whole idea behind correctly, I would personally write that stuff more *like*:

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
CALL :f_RecurseMd5 "%~dp0"
GOTO :EOF


:f_RecurseMd5 %_DirNames%
SET "_Dir1=%~1"
IF NOT "%_Dir1:~-1,1%"=="\" SET _Dir1=%_Dir1%\

FOR /F  "tokens=* delims=" %%? IN ('DIR /-B/A-D "!_Dir1!"^|FIND /V /I "App.md5"') DO ECHO md5sum.exe "!_Dir1!%%?"
REM FOR /F "tokens=* delims=" %%? IN ('DIR /-B/A-D "!_Dir1!"^|FIND /V /I "App.md5"') DO md5sum.exe "!_Dir1!%%?">>App.md5

FOR /F "tokens=* delims=" %%? IN ('dir /-B /AD "!_Dir1!"') DO IF EXIST "!_Dir1!%%?\" (CALL :f_RecurseMd5 "!_Dir1!%%?\")


:f_CleanUp
SET _Dir1= & ENDLOCAL&EXIT /B 0

Of course it still needs to be tested/validated.

jaclaz

 

Link to comment
Share on other sites

 

Thanks as always my friend,

This shows how much I forget after I haven't been actively writing batch for a while.

The routine as a whole was/is its own separate program that is called by an external application, as is md5sum.exe, so your comments regarding it are appropriate. Separating the actual "loop" into a separate routine helped simplify things. I sometimes "forget" about piping to "FIND", along with " /o-n " not being needed, so thanks for the reminders. I tried FIND as you wrote and it worked as expected, But when I changed how the routine was called, and referenced the location of md5sum.exe as being in the same folder as the this and the calling application, I realized I could also pass in the location of the temporary App.md5 as external to the folder I'm processing and then not need to check for it at all. To get the output from md5sum,exe to be formatted the way I wanted it, the working location has to be the folder of interest, which my previous method assumed, but that was easily accomplished with a pushd/popd. And your reminder that directories should always end with a "\" also simplified things a bit in the "loop". When I was dealing with some commands that had a trailing back slash and some that didn't, I got hung up on trying to work without one in all cases, and you demonstrated that it is usually easier to just add them back where they are missing, such as in the second "FOR". I was also able to move the cleanup and the check for the trailing backslash to the "outer" part of the routine to make it just a little bit cleaner.

So this is how things turned out:

 

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
SET "_Dir=%~1"
IF NOT "!_Dir:~-1,1!"=="\" SET "_Dir=!_Dir!\"
SET "_Tmp=%~2"
SET "_Md5=%~dp0%md5sum.exe"
pushd "!Dir!"
CALL :f_RecurseMd5
popd
SET "_Dir=" & SET "_Tmp=" & SET "_Md5=" & ENDLOCAL&EXIT

:f_RecurseMd5 %_DirNames%
(SET "_Dir=%~1")
FOR /F "tokens=* delims=" %%G IN ('DIR /-B/A-D "!_Dir!"') DO !_Md5! "!_Dir!%%G">>"!_Tmp!"
FOR /F "tokens=* delims=" %%G IN ('DIR /-B /AD "!_Dir!"') DO IF EXIST "!_Dir!%%G\" (CALL :f_RecurseMd5 "!_Dir!%%G\")
ENDLOCAL&EXIT


See anything else I missed?

Thanks again for the response and the help.

Cheers and Regards
 

Edited by bphlpt
formatting
Link to comment
Share on other sites

1 hour ago, bphlpt said:

This shows how much I forget after I haven't been actively writing batch for a while.

Naah, most of the time it is just one's own "writing style", or - if you prefer - there is more than one way to skin a cat (though none that the cat would appreciate ;)).

 

1 hour ago, bphlpt said:

And your reminder that directories should always end with a "\" also simplified things a bit in the "loop". When I was dealing with some commands that had a trailing back slash and some that didn't, I got hung up on trying to work without one in all cases, and you demonstrated that it is usually easier to just add them back where they are missing, such as in the second "FOR".

Yep, adding them when missing AND removing duplicates when they are already there, and check (once and for all) if they are included in quotes (needed for paths with spaces) i.e. (example):

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
SET "_Dir=%~1"
:: _Dir is not enclosed in quotes, stripped by the ~
CALL :validate_dir _Dir
SET _Dir
GOTO :EOF


:validate_dir
:: make sure it ends with backslash
SET %1=!%1!\
::make sure it ends with only one backslash and enclose it in double quotes
SET %1="!%1:\\=\!"
GOTO :EOF

 

1 hour ago, bphlpt said:

See anything else I missed?

Thanks again for the response and the help.

Cheers and Regards
 

You are welcome :), nothing missed that I can see, what I see unneeded is the ENDLOCAL&EXIT :dubbio: (the first can - should - be replaced by a GOTO :EOF, the last can - as well should - be replaced by a GOTO :EOF or, if it is the end of the batch, it's function is automatically performed by the actual EOF).

But again it is probably a question of writing style, to me the "main" of the program must always end with a GOTO :EOF and as well each and every subroutine must begin with a :label and end with a GOTO :EOF.

jaclaz

Edited by jaclaz
Link to comment
Share on other sites

55 minutes ago, jaclaz said:

Naah, most of the time it is just one's own "writing style"...

.., what I see unneeded is the ENDLOCAL&EXIT :dubbio: (the first can - should - be replaced by a GOTO :EOF, the last can - as well should - be replaced by a GOTO :EOF or, if it is the end of the batch, it's function is automatically performed by the actual EOF).

But again it is probably a question of writing style, to me the "main" of the program must always end with a GOTO :EOF and as well each and every subroutine must begin with a :label and end with a GOTO :EOF.

I've written some code in the past where I made extensive use of passing back ERRORLEVEL to indicate which error occurred, and then just got in the habit of always ending my routines that way. I didn't see it as a problem since according to SS64:


EXIT /b has the option to set a specific errorlevel, EXIT /b 0 for success, EXIT /b 1 (or greater) for an error.
The exit code can be an integer of up to 10 digits in length (positive or negative).

EXIT without an ExitCode acts the same as goto:eof and will not alter the ERRORLEVEL

As to your validating directories and dealing with quotes, you might find these two routines interesting, though I'm sure you could improve/streamline them. (You would have to adapt them to be sure that a directory does indeed end in one and only one backslash)

:: #############################################################################

:: #############################################################################
:: :f_QualDir "%_DirName%" _DirVariable
::
:: Convert a name to a path.
::
:: Usage: CALL :f_QualDir "%_DirName%" _DirVariable
::
:: This function takes as input a directory name or complete or partial path,
:: surrounded by any number of MATCHED qoutes, (if any spaces are in the name AT
:: LEAST ONE set of quotes is REQUIRED), the directory location can be relative
:: or absolute, and can have an ending back slash or not.  The result - a fully
:: qualified directory path, without quotes, and without a backslash - is
:: assigned to the variable in the second argument.  To be sure that any
:: potential empty string is handled correctly, it is suggested to ALWAYS
:: enclose the %_DirName% string in qoutes ["], extra levels of quotes will be
:: safely removed.  An empty string [""] will evaluate to the current directory.
:: Periods or dots [.] are evaluated the same way they are if you use them on
:: the command line.  A single dot [.] evaluates to the current directory, two
:: dots [..] evaluate to the parent directory, [..\..] evaluates to the next
:: parent, [..\..\..] to the next parent, etc.  It will automatically "stop" at
:: the drive level, ie C:, or D:, or whatever.  [\], [\.], [\..], or anything
:: with a backslash [\] as the left-most character, evaluates to the drive
:: level.  Since a single dot evaluates to the current directory, [.\.\.\.\.\.\]
:: will also evaluate to the current directory.  [..\Temp] is at the same level
:: as the current directory.  ["..\..\Fred's files\Myjunk"] is a valid
:: %_DirName%.  The directory does NOT have to exist and is NOT created.  This
:: simply converts a name to a path.
::
:: Dependencies: :f_DeMultiQuote
::
:: Upon exit, a fully qualified path name is assigned to "_DirVariable".
:: ERRORLEVEL is set to 0.
:: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
:f_QualDir "%_DirName%" _DirVariable
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
(SET _QDir=%1)&(CALL :f_DeMultiQuote _QDir)
IF "."=="!_QDir:~-1!" SET _QDir=!_QDir:~0,-1!
FOR %%G IN ("%_QDir%") DO FOR %%H IN ("%%~G.\") DO (SET "_QDir=%%~fH")
ENDLOCAL&(SET "%2=%_QDir:~0,-1%")&EXIT /B 0
::
:: #############################################################################

:: #############################################################################
:: :f_DeMultiQuote _DQVar
::
:: Remove multiple levels of quotes from a variable.
::
:: Usage: CALL :f_DeMultiQuote _DQVar
::
:: This function removes any number of MATCHED quotes from the outside of a
:: string variable and reassigns the result back to the same variable.
::
:: Dependencies: None [_DQVar must be provided, but it can be empty]
::
:: Upon exit, ERRORLEVEL is set to 0.
:: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
:f_DeMultiQuote _DQVar
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
(CALL SET _String=%%%1%%)
IF [!_String:~0^,1!]==[^"] (
:s_dmqAgain
	IF [!_String:~-1!]==[^"] ((SET _String=!_String:~1,-1!)
		IF [!_String:~0^,1!]==[^"] GOTO s_dmqAgain)
)
ENDLOCAL&SET %1=%_String%
EXIT /B 0
::
:: #############################################################################


Cheers and Regards

Link to comment
Share on other sites

Well, the subroutines I write don't generate errors ;), as said it is a case of writing style.

Anyway, the ENDLOCAL is unneeded (there are very few cases when you need to NOT run the whole batch "LOCAL" and thus you need to exit the mode).

The subroutine about MATCHED quotes is not relevant speaking of Paths.

A path is EITHER enclosed in quotes OR it is not (you can't have a quote or any matched couple of quotes in a path), SO you can strip ALL quotes  and reenclose the path in quotes (and this covers BOTH matched and UNmatched quotes) i.e.:

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
SET _Dir=%*
:: _Dir may be enclosed in quotes, or simply contain one or more quotes
CALL :validate_dir _Dir
SET _Dir
GOTO :EOF


:validate_dir
::make sure it contains no quotes
SET %1=!%1:^"=!

:: make sure it ends with backslash
SET %1=!%1!\


::make sure it ends with only one backslash and enclose it in double quotes
SET %1="!%1:\\=\!"
GOTO :EOF

It is much simpler (as it does a much simpler transformation).

jaclaz

 

Link to comment
Share on other sites

Well, when you put it THAT way... :)

Point taken about ENDLOCAL. The matched quote routine was written to deal with other various variables, and was just reused for this application since it was handy, but your routine is MUCH more efficient when dealing specifically with paths.

The errors aren't MY errors, but because of the data dealt with or user input. But like I said at the beginning, I'm sometimes guilty of the belt + suspenders approach to coding.

Cheers and Regards

Link to comment
Share on other sites

14 hours ago, bphlpt said:

The errors aren't MY errors, but because of the data dealt with or user input.

I know :), I was only pulling your leg a bit.

 

14 hours ago, bphlpt said:

But like I said at the beginning, I'm sometimes guilty of the belt + suspenders approach to coding.

Yep :), you know, I tend to make the exact opposite, believing that simplicity is the ultimate sophistication:

https://quoteinvestigator.com/2015/04/02/simple/

I try to remove as much as I can, and possibly even something more, so I am always on the brink of creating havoc :w00t: because I omitted some checks :ph34r:.

Since you like this kind of stuff, how to make sure that the "path" does not contain any non-legal characters? :dubbio:

Let's decide which characters are not allowed in a path:

https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file

Quote

The following reserved characters:

  • < (less than)
  • > (greater than)
  • : (colon)
  • " (double quote)
  • / (forward slash)
  • \ (backslash)
  • | (vertical bar or pipe)
  • ? (question mark)
  • * (asterisk)

(of course the backslash is allowed in a path, it is not in a filename, and of course the colon is allowed in a path, but ONLY as second character)

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
SET _Dir=%*
:: _Dir may be enclosed in quotes, or simply contain one or more quotes
CALL :validate_dir _Dir
::Now _Dir is surely quoted with matched quotes
SET _Dir
GOTO :EOF


:validate_dir
::make sure it contains no quotes
SET %1=!%1:^"=!

::make sure it contains none of <>:/|?*
::let us assume that it begins with a drive letter followed by a colon
IF "!%1:~1,1!"==":" (SET DlP=!%1:~2,254!) ELSE (SET DlP=ERROR&ECHO !Dlp!&GOTO :EOF) 
FOR /F "tokens=2 delims=<>:/|?*" %%? IN ("!DlP! ") DO (SET DlP=ERROR&ECHO !Dlp!&GOTO :EOF) 


:: make sure it ends with backslash
SET %1=!%1!\


::make sure it ends with only one backslash and enclose it in double quotes
SET %1="!%1:\\=\!"
GOTO :EOF

jaclaz

Link to comment
Share on other sites

Yeah, these kinds of things can be a fun kind of puzzle, and good practice. :)

Minor questions:

  • It's not necessary to check whether the drive letter is a valid character, or can there be a drive "#" or "}"? AFAIK, you can only have 26 drive letters., all alphabetic characters a-z.
  • Isn't there another way to indicate "all remaining characters" other than "254" in - (SET DlP=!%1:~2,254!) -? Or is that not what that is implying? I can't remember off the top of my head. I was assuming you were using a maximum path length of 256 characters. And what if more than 256 characters are entered? I think the limits are supposed to be 260 characters including the drive letter, colon, path including trailing backslash and/or file name with extension, and a terminating null character. Of course the more recent versions of NTFS can handle longer limits, but then Windows Explorer won't be able to deal with them very easily. You'll end up having to rename various folders before you are even able to move or delete files, as I've run into on more than one occasion.
  • Why the trailing space after !DlP! in - ("!DlP! ") - ?
  • If the input string is not in the drive letter, colon, rest of path format, you currently consider it a fatal error. Is this a case of you oversimplifying things? A valid path does not require a leading drive plus colon.
  • It's OK to just throw away any extra quote marks in and around the path, add a missing trailing backslash, and assume the remainder is OK, but if any other illegal characters are found then it's a fatal error? I just try to be consistent. :)

EDIT: And, of course, the code will probably be different if we are testing for an existing location, or just a theoretical, correctly formatted string, to possibly be used at a different location with different resources than the current system has. [ I know, that comment is somewhat argumentative, no offense intended ]

I think the testing of the first letter could be done with something "like":

SET "Valid=ABCDEFGHIJKLMNOPQRSTUVWXYZ"
FOR /L %%G in (0,1,25) DO IF /I "!%1:~0,1!"=="!Valid:~%%G,1!:" (GOTO :keep_testing) ELSE (SET DlP=ERROR&ECHO !Dlp!&GOTO :EOF) 

For testing an actual location, I suppose this could be adapted: (found here)

for /f "tokens=1,2 delims=d" %%A in ("-%~a1") do if "%%B" neq "" (
  echo %1 is a folder
) else if "%%A" neq "-" (
  echo %1 is a file
) else (
  echo %1 does not exist
)
Note - This technique is intended to be used for a path without any wildcards (a single specific file or folder). 
If the provided path includes one or more wildcards, then it provides the result for the first file or folder that the file system encounters. 
Identical directory structures may give different sort order results depending on the underlying file system (FAT32, NTFS, etc.)

Thanks for the fun and feedback.

Cheers and Regards

Edited by bphlpt
Link to comment
Share on other sites

11 hours ago, bphlpt said:

Minor questions:

  1. It's not necessary to check whether the drive letter is a valid character, or can there be a drive "#" or "}"? AFAIK, you can only have 26 drive letters., all alphabetic characters a-z.
  2. Isn't there another way to indicate "all remaining characters" other than "254" in - (SET DlP=!%1:~2,254!) -? Or is that not what that is implying? I can't remember off the top of my head. I was assuming you were using a maximum path length of 256 characters. And what if more than 256 characters are entered? I think the limits are supposed to be 260 characters including the drive letter, colon, path including trailing backslash and/or file name with extension, and a terminating null character. Of course the more recent versions of NTFS can handle longer limits, but then Windows Explorer won't be able to deal with them very easily. You'll end up having to rename various folders before you are even able to move or delete files, as I've run into on more than one occasion.
  3. Why the trailing space after !DlP! in - ("!DlP! ") - ?
  4. If the input string is not in the drive letter, colon, rest of path format, you currently consider it a fatal error. Is this a case of you oversimplifying things? A valid path does not require a leading drive plus colon.
  5. It's OK to just throw away any extra quote marks in and around the path, add a missing trailing backslash, and assume the remainder is OK, but if any other illegal characters are found then it's a fatal error? I just try to be consistent. :)

 

1. Well, you can check it, of course. Something *like*:

FOR /F "tokens=1 delims=ABCDEFGHIJHKLMNOPQRSTUVWZabcdefghijklmnopqrstuvwxyz" %%? IN ("!%1!") DO (
SET CMB=%%?
IF NOT "!CMB:~0,1!"==":" (SET DlP=ERROR&ECHO !Dlp!&GOTO :EOF) 
)

would do.

2. Sure, use SET DlP=!%1:~2! instead of SET DlP=!%1:~2,254! the 254 was only an attempt to limit the length of the path, considering that maybe a backlash was needed and leaving a few characters for a sub-sub-sub ... directory.

3. That is the "clever" part ;), and you should think about it and answer yourself the question :whistle:.

4. Not necessary a "fatal" error, one can change the code at will, as said it is a simple assumption that the path needs to start with a drive letter and a colon, the issue may be with those cases where you use relative paths (i.e. .\ or ..\) or - and this is one of the show stopper, UNC syntaxes and similar  good examples might be:

DIR \\?\C:\

or:

DIR \\.\C:\

but if you want to recognize that, you will need to add complications and the simple backslash replacement won't work anymore "as is" (and of course introduces the ? as a valid character - in a fixed position - in a path)

5. As said the treating of double quotes is correct, double quotes cannot be inside a valid path AND can only be, matched, outside it and enclosing it, i.e. EITHER no quotes OR quotes enclosing it  tertium non datur:

https://en.wikipedia.org/wiki/Law_of_excluded_middle

Having a path ending with a single backslash is correct. <last character is a full stop or period

Looking for  illegal characters, is - obviously - legal, if there is an illegal character, then the path is not valid (it is illegal), so yes, if any of the no-no characters is found the only possibility is to have a fatal error.

Point being, what if all the checks performed till now are not enough?

If the path is an existing path one could do, with the "as sanitized as possible" path variable a further check, *like*

CALL :is_expanded_path !%1!

GOTO :EOF

:is_expanded_path
IF  %1=="%~dp1" ECHO Path %1 seems fine
IF  NOT %1=="%~dp1" SET DlP=ERROR&ECHO !Dlp!&GOTO :EOF

that might help.

And now, for the fun of it, try to visualize the results of the following batch before running it:

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
SET _Dir="C:\*"
CALL :is_expanded_path !_Dir!
SET _Dir="C:\/"
CALL :is_expanded_path !_Dir!
SET _Dir="C:\*/"
CALL :is_expanded_path !_Dir!

SET Head="C:\
SET Body=
SET Tail= /"
FOR /L %%? IN (1,1,12) DO (
SET Body=!Body!?
SET _Dir=%Head%!Body!%Tail%

CALL :is_expanded_path !_Dir! %%?
)
ECHO .

SET _Dir="C:\|/"
CALL :is_expanded_path !_Dir!

SET _Dir="C:\P*/"
CALL :is_expanded_path !_Dir!

SET _Dir="C:\*a?*/"
CALL :is_expanded_path !_Dir!

GOTO :EOF


:is_expanded_path
ECHO %2 "%~dp1" 

 

anything unexpected? :dubbio:

jaclaz

 

Link to comment
Share on other sites

Definitely NOT what was expected., and I'm afraid my brain is too foggy for the moment to come up with an explanation. :(

I'll definitely have to think about that for awhile. Care to point me in the right direction, or do I need to suffer for my sins for awhile first?

To change the subject a bit, and I'll start a new thread if more appropriate, I've started playing with Powershell. I'm having a devil of a time calling an external program, 7z.exe in this case, from my powershell script, and passing parameters to it and having them interpreted correctly. I know the parameters are correct, since I can call 7z.exe with the same parameters from batch and they are executed just fine, Same if I call a batch routine from powershell which then calls 7z.exe - works just fine. But if I try to call 7z.exe directly from powershell, I get the response "Command line error: Unsupported command:" and then it prints out the exact command I sent, the exact command that has been working for me and others for years, but now it doesn't like it. I tried to simplify the command to a ridiculous extent, even copying directly from the 7z documentation the simplest command I could find, just to see if I could get it to accept ANYTHING as a valid command, but no luck. It is absolutely driving me crazy!

Maybe some sleep will help with both problems.

Cheers and Regards

Link to comment
Share on other sites

I have not enough experience with Powerhell (please notice the correct spelling ;)) to give you any meaningful help, but it is a known issue (parameters) assuming you are correctly using the stupid leading "&" (ampersand):

https://social.technet.microsoft.com/wiki/contents/articles/7703.powershell-running-executables.aspx#reCodeBlock

https://social.technet.microsoft.com/wiki/contents/articles/7703.powershell-running-executables.aspx#The_Call_Operator_amp

(but later vestions should not need it :dubbio:) for parameters see here

https://stackoverflow.com/questions/1673967/how-to-run-an-exe-file-in-powershell-with-parameters-with-spaces-and-quotes

 the staff is so stupidly complex  that they made a dedicated program, echoargs, part of the:

https://archive.codeplex.com/?p=pscx

to check what Powershell actually "sees":

 https://rkeithhill.wordpress.com/2012/01/02/powershell-v3-ctp2-provides-better-argument-passing-to-exes/

and:

https://web.archive.org/web/20170727144215/http://edgylogic.com/blog/powershell-and-external-commands-done-right/

 

And of course, if you take simplicity out of the equation :w00t: :ph34r: you can try using this:

https://www.mobzystems.com/code/7-zip-powershell-module/

https://gist.github.com/mobzystems/793007db28e3ffcc20e2

or this:

https://www.powershellgallery.com/packages/7Zip4Powershell/1.9.0

jaclaz

 

Link to comment
Share on other sites

What Os and what version of PS are you using? How exactly are you calling 7zip?

As earlier said, Povwershell 2.0 had some quirks when running external commands, and some were solved or worked around (workarounded?) in later versions. Too many possible root causes to guess.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...