CMD: Fails with %1 - windows

Recently i posted a question about what the variable is of a file which you open with a batch file, which is %1.
I used this, to let my batch file copy %1 to a specific location.
After doing this, debugging and a lot of time, and it actually worked, after debugging it more, adding some features, and some more debugging, it stopped working. This is a snippet, where it seems it goes wrong (i tried #echo on to get my info.)
if not "%1:~-8%"==".package" (
set error=yes
set errmes1=File %1 does not have a .package extension.
goto :errpkg
)
copy "%1" "C:\path_to\folder"
:errpkg
cls
echo %errmes1%
...
(%1=C:\path\to\it\file_something.package)
This is the point were it goes wrong, i guess. Because it ends up with this message. What it SHOULD do, is at if not checking if the file has a .package extension. then, set error=yes, just says what it does, set errmes1 sets an error message. and then the goto just goes to some place in the batch file where it explains what the problem is. (using %errmes1%)
So, that's it. Here is where it goes wrong. I am 100% sure it has a .package extension. Could anyone help me, to tell me what the problem is?

I seriously wonder how you ever got that to work. The substring syntax only works on environment variables (well, and pseudo-variables such as %cd%). That means you can do
%foo:~-8%
but not
%1:~-8%
This wouldn't even work if you had an environment variable named %1%.
Anyway, the usual idiom to check for the extension of an argument is
%~x1
So why complicate things more than necessary?

Tried using %~x1 to extract the extension? Your syntax doesn't work for me.
Also, can't setting variables inside the conditional get screwy in cmd.exe?

Related

My batch files (.cmd) sometimes execute partial lines

I've a strange problem that I have never seen before in my ~30 years of working with batch files. Given a dummy CMD file such as this:
#echo off
:somelabel
echo Testing something
dir /b
echo All is well.
:end
This mostly runs as expected, but sometimes I get output such as 'ing something' is not recognized as an internal or external command, operable program or batch file.
That's clearly an occurrence where it has chopped off a bit of a line and attempted to execute the rest of it. When this happens, it's always a 'random' fraction of a 'random' line; it's not always line X, or losing Y characters, or occurring where I have a particular character combination. Nor does it affect only echo statements, it could just as well try to execute abel or ir /b.
My system is a fully updated Win2008 R2, running in VirtualBox 5.0.2, running in a fully upgraded Linux Mint, running on a Lenovo ThinkPad. The scripts are all UTF-8 encoded.
... what's going on? How can I avoid this?
Well, in my experience there is no way that a normal Batch file may present this behavior. The only way this can happen is if the Batch file is modified while it is running, so the cmd.exe processor continue reading the "next line" of the Batch file, but at that position in the modified file there is a part of another line. The example below show this behavior:
#echo off
:somelabel
(for /F "skip=1 delims=" %%a in (%~NX0) do echo %%a) > temp.tmp
del "%~NX0" & ren temp.tmp "%~NX0"
echo Testing something
echo All is well.
:end
In this example after the del ... & ren ... line is executed, the next line to execute will be read at the beginning of original position of echo Testing something line, but now at that point there is its ing something part because the first #echo off line was deleted. See this:
#echo offRL
echo Testing something
In previous scheme the RL letters exemplify the CR+LF control characters, so the next position is at the "ing".
Credit goes to #SomethingDark for the comment:
The command line doesn't play nice with UTF-8. Use ANSI instead.
This seems to have resolved the issue (as far as I can be sure with an intermittent problem).
I know this is a couple years late but I actually found the most accurate answer.
I actually did some testing on why it could register only partial code and got the answer. If you are editing the code and run batch while still open, it has a partial chance of only registering partial code. This is actually correct, nothing with encoding although that might be part of it except still does it to me with ANSI but with some testing, I realize that isn't it and that it is because batch cannot catch up with you when editing the code.
I did type a comment on the answer marked as best and said what I think but after further testing on the question I realized the pattern is when editing the code and running the batch file while still open, almost right away it seems to only read partial code.
When you said it seems to work when changing encoding to ANSI, did you just run it or did you edit it and run it at the same time. The main reason I did want to answer this is because my encoding method on a batch file I am working on is in ANSI and still causes the error of partially reading the code. Once I read Aacini answer, it gave me a thought of it and that he is partially correct to KlaymenDK situation.
Do prevent the error of partially reading the code modify and wait a bit than run and if that doesn't work than restart it. If you are planning on publicly posting it, you don't really have to worry about the problem because it would most likely only occur if you edit the code while running it. Nothing that could really be a problem with your code as I know.
Recently I run into the same problem, although the cause might be different.
In my case there was an REM command with text which have special characters in other languange. After I erased the REM command, the problem was solved.
For disclosure the problem did not happened in all computers the code was executed, and still dont know why will special characters cause the batch file to execute partial lines.

How to do a for loop in windows command line?

I was wondering if this was possible? I'm not familiar with using windows command line, but I have to use it for a project I'm working on. I have a a number of files, for which I need to perform a function for each. I'm used to working with python, but obviously this is a bit different, so I was hoping for some help.
Basically I need the for loop to iterate through 17 files in a folder, perform a function on each (that's using the specific software I have here for the project) and then that will output a file with a unique name (the function normally requires me to state the output file name) I would suck it up and just do it by hand for each of the 17, but basically it's creating a database of a file, and then comparing it to each of the 17. It needs to be iterated through several hundred times though. Using a for loop could save me days of work.
Suggestions?
The commandline interpreter does indeed have a FOR construct that you can use from the command prompt or from within a batch file.
For your purpose, you probably want something like:
FOR %i IN (*.ext) DO my-function %i
Which will result in the name of each file with extension *.ext in the current directory being passed to my-function (which could, for example, be another .bat file).
The (*.ext) part is the "filespec", and is pretty flexible with how you specify sets of files. For example, you could do:
FOR %i IN (C:\Some\Other\Dir\*.ext) DO my-function %i
To perform an operation in a different directory.
There are scores of options for the filespec and FOR in general. See
HELP FOR
from the command prompt for more information.
This may help you find what you're looking for...
Batch script loop
My answer is as follows:
#echo off
:start
set /a var+=1
if %var% EQU 100 goto end
:: Code you want to run goes here
goto start
:end
echo var has reached %var%.
pause
exit
The first set of commands under the start label loops until a variable, %var% reaches 100. Once this happens it will notify you and allow you to exit. This code can be adapted to your needs by changing the 100 to 17 and putting your code or using a call command followed by the batch file's path (Shift+Right Click on file and select "Copy as Path") where the comment is placed.
You might also consider adding ".
For example for %i in (*.wav) do opusenc "%~ni.wav" "%~ni.opus" is very good idea.

Batch- string search on Windows PATH

I am writing an batch file in Windows to run post-installation scripts, and one of the things that needs to be done is to add a directory to the system path.
The script is working, and it does something like this:
setx Path "%PATH%;c:\path\to\add" -m
This is setting the path correctly, but this script could potentially be run multiple times if the user reinstalls the program.
I would like to search the string for c:\path\to\add so I don't keep adding the same path over and over to the system path. This is pretty trivial in Linux with sed, but I don't know what the command is in Windows. I've found findstr, but this seems to only work on files.
Is this possible in Windows without installing additional software?
EDIT:
I'm using Inno Setup to create the install executable.
At the risk of some downvotes till an expert provides a sound way of doing this,
the below removes the specific path from the environment variable if it exists, so that it can be added again:
set str=%path%
:: str is the same with path
set str=%str:;C:\Path\To\Add=%
:: ";c:\path\to\add" is now removed from str
setx Path "%str%;c:\path\to\add" -m
:: proceed with setting the path
This carries the risk of removing the string if it is in fact actually a part of a path, for instance c:\path\to\add\somefolder. Also if the path actually ends with a \, or it is the first entry and it in fact does not start with ;, etc..
Various forms can be called consecutively to circumvent some of these,
set str=%str:;C:\Path\To\Add\;=;%
set str=%str:;C:\Path\To\Add;=;%
set str=%str:;C:\Path\To\Add\=%
set str=%str:C:\Path\To\Add\;=%
set str=%str:;C:\Path\To\Add=%
But, AAMOF I'n not sure this is a sane way of doing this..
This is my code snippet to find the "cvsnt" path in the PATH variable.
if not "x%PATH:cvsnt=%" == "x%PATH%" goto proceed
set PATH=w:\build-repository\cvsnt\2.5.03-2382;%PATH%
echo Path added
:proceed
The part to look at is
not "x%PATH:cvsnt=%" == "x%PATH%"
First I replace all occurrences of "cvsnt" with an empty string. The result is compared to PATH without replacement of "cvsnt". If they are not equal because of "cvsnt" was replaced then it exists in PATH and the code can proceed.
The starting x before %PATH% is only a placeholder to protect against certain "improper" starting characters. see Batch file: Find if substring is in string (not in a file)
The setx utility has a drawback, it can not handle variables longer than 1024 characters.
I have been wrote a script to handle cases longer than the limit and without a need to install anything. Answered the question here: Set environment variables with NSIS in Window 7
Instead of adding the path each time - you could check if the executable you are looking for can be found within the path using a command like this:
for %f in (cmd.exe) do if [%~$PATH:f]==[] setx Path "%PATH%;c:\path\to\add" -m
Make sure to check for /? to read more about the magic of %~$PATH:f.
This is a bit of a hackish workaround, but follows the logic you expect:
Search the PATH
Conditionally add to the PATH
It never removes anything from the PATH, so there's no fear of screwing up Windows by removing something accidently. Also, it checks the PATH variable directly, so you don't have to worry about another file with the same name that lives somewhere on the PATH.
echo %PATH% > myTmpPath.tmp
find /C /I "c:\path\to\add" myTmpPath.tmp
if %ERRORLEVEL% neq 0 setx PATH "%PATH%;c:\path\to\add"
del myTmpPath.tmp
I hate using temporary files, but it's quick and dirty, and probably safer than removing something from the PATH.
The third line is the only tricky one. Basically, this line tests the outcome of the FIND command above. Rob van der Woude states:
FIND returns an errorlevel of 1 or higher if the search string wasn't found.
He also explains:
Some executables return negative numbers for errorlevels! However, this can be
fixed by using the following code to check for non-zero return codes:
IF %ERRORLEVEL% NEQ 0 ...

Programming in a batch script

Hey all I have a simple problem I was hoping someone can give me assistance with. I'm trying to get WMIC to return output however on different machines, the executable is in different directories. Is there a method to check all directories I list to get it to run, e.g.:
IF EXIST
wmic=c:\checkhere\
ELSE
wmic=c:\checkthisone\
CONTINUE
The following is a simple way of setting an environment variable to some path that has a file you are looking for. A rather brain dead way but easy to understand/change:
if exist c:\path1\some.exe set asdf=c:\path1\
if exist c:\path2\some.exe set asdf=c:\path2\
if exist c:\path3\some.exe set asdf=c:\path3\
if %asdf%x=x goto couldnotfindit
set path=%path%;%asdf%
As an option You could add all of them to the PATH variable and simply run wmic.

starting a windows executable via batch script, exe not in Program Files

This is probably batch scripting 101, but I can't find any clear explanation/documentation on why this is happening or if my workaround is actually the solution. So basically any terminology or links to good sources is really appreciated.
So I have a program I want to execute via batch script (along with several other programs). It's the only one where the exe is not in a Program Files folder. I can get it to start like this:
C:\WeirdProgram\WeirdProgramModule\weirdmodule.exe
But I get an error along the lines of:
Run-time Error '3024':
Could not find file
C:\Users\MyUserName\Desktop\ModuleSettings.mdb
So it seems that the program is looking for its settings files from the same location that the batch script starts up. Given that I finally got everything to work by doing the following:
cd C:\WeirdProgram\WeirdProgramModule\
weirdmodule.exe
That works fine, and it's not the end of the world to have to go this route (just one extra line), but I've convinced myself that I'm doing something wrong based on lack of basic understanding.
Anybody know or can point me to why it works this way?
Oh, and doing the following:
start "C:\WeirdProgram\WeirdProgramModule\weirdmodule.exe"
doesn't do anything at all.
Thanks,
you are doing it perfectly :-)
the executable is probably looking for this file in the "current working directory", which is being set, when you "cd" to it before.
you can set your working directory manually by creating a shortcut to your batch file; right click; properties.
edit:
you can also set your current working directory using the start command:
start "Title" /D "C:\WeirdProgram\WeirdProgramModule\" "weirdmodule.exe"
edit:
If you like to pass params, just add them to the executable filename as you would in a regular shortcut:
start "Title" /D "C:\WeirdProgram\WeirdProgramModule\" "weirdmodule.exe" "param1 param2"
or
start "Title" /D "C:\WeirdProgram\WeirdProgramModule\" "weirdmodule.exe param1 param2"
For reference, the syntax is described here: http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/ntcmds.mspx?mfr=true.
What's happening is that weirdmodule.exe is looking in the "current directory" for the .mdb file. You might be able to tell it where to find the .mdb file through a command line parameter or some other configuration method (registry or .ini file maybe). How you'd specify the location is entirely up to the weirdmodule.exe program, though.
Other than that, your current workaround is probably what you're stuck with.
As far as your problem with using start.exe... the start.exe program has the very, very odd behavior (bizarre behavior in my opinion) of treating the first parameter as the 'title' to put in the window if (and only if) the first parameter is in quotes. So you have a couple of options:
Don't use quotes to specify the program. This works for you because you don't need quotes (there aren't any spaces or other special characters in the path that would require quoting it):
start C:\WeirdProgram\WeirdProgramModule\weirdmodule.exe
Give an empty (or some other string) title as the first parameter. This is something you'd have to do if your path required quotes:
start "" "C:\WeirdProgram\WeirdProgramModule\weirdmodule.exe"

Resources