Loop Syntax error in MS-DOS 6.22 - loops

I'm trying a script to get the last modified date on a virtual PC running MS DOS 6.22.
But whenever I find a solution which includes a loop, it shows syntax error in the console.
Here's one of the lines that shows this :
for /d %%a in ("C:\log") do echo Modified date: %%~ta
Is dos 6.22 incompatible with the loops ? I have a lot of restrictions with this version (can't use robocopy, date, etc...)

The loop syntax is supported, but a bit limited (see also for /?).
FOR %A in (filelist) do myCmd %%A
So there are no switches at all.
As I remember in the most cases it wasn't possible to catch data with DOS.
It was really hard stuff even to split a simple string.
But if you absolutly need it (or have fun with it) you can split a string with a FOR loop into the first character and the rest by
for %%A in (/%var%) do echo %%A
But to save the first character is a bit tricky...
Or you could use edlin or debug to parse strings.
Advanced stuff like request the last modified date of a file was behind the possibilities of ms-dos.
But why you don't try it from your host computer to access the inner file system of the VM?
Then you could also use all modern technologies like cmd.exe batch

Related

Use content of a file in a string

I have a file (let's call it version.txt) that contains a version number and some text:
v5.02
Some text explaining
where and how this
number is used
Based on this answer, I use
set /p version=<version.txt
to store the first line of the file in the version variable. Now I'm trying to write a batch script that operates on folders that contain this version number in their name. However, I get unexpected results because something seems to go wrong when I insert the variable in a path. For example, this script
#set /p version=<version.txt
#echo C:\some\folder\%version%\some\file.exe
prints
C:\some\folder\v5.02
instead of
C:\some\folder\v5.02\some\file.exe
What's going on? I have a feeling there are hidden characters of some sort at the end of the text in the variable, because setting the variable by hand to a constant in the script works.
Edit: I'm using Windows 10 with Notepad++ as my editor, if it helps.
I can only replicate your issue, when version.txt uses Unix line endings (LF) instead of Windows (CRLF). for /f is immune to this issue:
for /f "delims=" %%a in (version.txt) do set "verion=%%a" & goto :skip
:skip
echo C:\some\folder\%version%\some\file.exe
goto :skip breaks the loop after reading the first line.
Since everything I tried didn't seem to work, the solution I found in the end is to call the batch script from a Python script. The Python script reads the first line of the version file and passes it as an argument to the batch script. Out of context, it is a bit of an inelegant solution, but in my case the batch script was already called by a Python script, so it's not that terrible.
Here is a minimal example:
version.txt
v5.02
Some text explaining
where and how this
number is used
script.bat
#echo C:\some\folder\release\%1\some\file.exe
script.py
import os
with open("version.txt") as f:
version = f.readline().rstrip()
os.system("cmd /c script.bat %s" % version)
Edit: Following Stephan's comment, I tried to change the line ending in the text file from LF to CRLF and it indeed solves the problem. However, since I don't really have control over everything that writes in that file, the solution above remains the most feasible in my case.
Edit 2: Stephan's answer (with the for loop) is actually a better solution than this one since it avoids having to transfer part of the work to the calling Python script.

Windows batch file ren using date variable

Learned batch a while ago in school, haven't ever used it until now b/c I had an idea. Just for fun I wanted to mess around with powercfg batteryreport with my new laptop, but I want to archive. I was going to try and figure out how to have the file powercfg batteryreport spits out changed in some sort of numerical order but I don't even know where to begin, so I decided to just make a new line that takes the current file created and adds the date. All of this is taking place inside of a special folder I created, so pathing isnt necessary.
#echo off
powercfg batteryreport
rename "battery-report.html" "batteryreport %date%.html"
This exact script works without the date variable, but never with it in, but of course I need a variable present in order to have multiple reports saved, as opposed to it writing over itself every time. I've tried messing with all spacings, quotes vs no quotes, no luck. Help (or a better way, preferably with explanation) would be greatly appreciated.
In all likelihood, your date format contains / which is illegal in a filename.
Use %date:/=-% in place of %date%. this converts each / to - (see set /? from the prompt for docco)
Equally, you could use %time::=.% o convert the time to a version usable in a filename.
To remove dayname, you need to use an intermediate variable:
set "dateonly=%date:* =%"
ren ... "...%dateonly:/=-%..."
The * means "all of the characters up to and including the first space" and this is replaced by nothing (the string following the =)
see set /? from the prompt for details.

Batch command double extension fix

Hi everybody i would like to ask how i can remove a mistakenly added second file extension using a batch script.
E.g. "test.aac.m4a" -> "test.m4a"
So the last extension is the right one which i want to have.
But this is ONLY the case for
.aac.m4a
-> .m4a
and
.m4a.aac
-> .aac
I know some batch scripting but
ren *.aac.m4a *.m4a
Won't work :(
Another thing worth mentioning would be that these double extensions come from my music software MusicBee.
I use mp4box on m4a files to extract the raw aac stream from the m4a container so i can edit it in other software.
Currently the syntax is:
mp4box.exe -raw 1 "<URL>" -out "<URL>".aac
The "<URL>" is the variable MusicBee will replace with the file url.
But this will add the .aac extension after the .m4a and i have no idea how to replace it instead. (and again when i repack the files ".aac -> .aac.m4a")
As far as i know MusicBee just replaces the variables and launches the batch code when activated so i think other batch code will work too.
Is it possible to prevent this double extension from even developing?
As always ANY help is apreciated!!
Thanks, Daniel
In preventing the double extension from developing I'm guessing you're not appending the file extension accordingly in the right way, I am however not familiar at all with Music Bee.
As for creating the right batch files that do what you want, I've used Advanced File Renamer in the past for all sorts of renaming patterns such as your case. It's freeware too! The program has a fairly advanced feature that allows users to write custom scripts in JavaScript user guide here. And can even generate batch scripts that do special renaming (as you've noted in the comments) for your specific use case.
For the other less advanced users the program has a GUI that makes it easy to do batch renames.
Best of all, if you're like me that avoids third party software installs just to do one thing as much as possible, the program has a portable mode that won't hook itself into your system, which is always good.
Read the manuals and guides there for more information. My answer might sound a little too much like advertising for it, but that's only because it's helped me so much in renaming my music a long time ago.
Here's a screenshot by the OP, RapidFireArts that shows how OP used the software to remove the second file extension.
It ought to be possible, but I have no idea how to work with your software to prevent the double extensions from occurring in the first place. But it is fairly easy to strip off the unwanted middle "extension".
If you know for a fact that none of your .m4a or .aac files are supposed to have multiple dots, then you could simply do the following:
ren *.m4a ???????????????????????????????????????????.m4a
ren *.aac ???????????????????????????????????????????.aac
Just make sure you have enough ? wildcards to match the longest name in your folder. See How does the Windows RENAME command interpret wildcards? for an explanation of why this solution works.
But sometimes file names legitimately have additional dots prior to the actual extension. If this is your case, then the following batch script will remove only the unwanted .m4a and .aac middle "extensions"
#echo off
for /f "eol=: delims=" %%A in ('dir /b /a-d *.m4a.aac *.aac.m4a') do (
for %%B in ("%%A") do ren "%%A" "%%~nB%%~xA"
)
Another option is to use my JREN.BAT regular expression file renaming utility. JREN.BAT is a hybrid JScript/batch script that runs natively on any Windows machine from XP onward. Ideally, the script should be placed within a folder that is included within your PATH. I like to use c:\utils for all of my non-standard utilities.
Once you have JREN.BAT, then all you would need would be
call jren "\.(m4a|aac)(?=\.(m4a|aac)$)" ""
Provided you understand regular expressions, and you take the time to read the built-in JREN help, then there are many wondrous things you can do with the utility. The help is accessed by issuing jren /? from the command line. You might want to use jren /?|more if you have not configured your console window to have a large buffer that enables scrolling to see prior output.
I use File Renamer Basic.
http://download.cnet.com/File-Renamer-Basic/3000-2248_4-10306538.html
It's Free

Input Error: There is no file extension

If this is a rookie mistake I apologize for wasting your time.
As part of a larger batch file to create a directory with today's date, copy and paste files to be backed up, change permissions and delete files older then X days I've run into a problem. Here's where it happens:
echo var D = new Date() > tmp.js
echo D = (D.getFullYear()*100+D.getMonth()+1)*100+D.getDate() >> tmp.js
echo WScript.Echo( 'set YYYYMMDD='+D ) >> tmp.js
echo #echo off > tmp.bat
cscript //nologo tmp.js >> tmp.bat
call tmp.bat
The command prompt spits back this error:
Input Error: There is no file extension in "C:\Users\name\Desktop\Error:".
So obviously the rest of the batch file fails but the weird thing is this works on one machine on the network but not the other.
Any help is greatly appreciated.
EDIT: there is one more line to that code that is returning the error, my mistake.
After I call tmp.bat:
mkdir "\\network\file\%YYYYMMDD%"
This code, as is, will not generate the indicated error
BUT, if the path to the batch file contains spaces, and the code is something like
cscript //nologo %~dp0\tmp.js
you will get the indicated error as the argument to cscript is incorrectly parsed because the space in the path to the js file. If this is the case (or something similar), quotes in the filename should solve it
cscript //nologo "%~dp0\tmp.js"
Also, the temporary batch file is not needed. Output from cscript can be directly read with the help of for command
set "tmpJS=%~dp0\tmp.js"
>"%tmpJS%" echo with(new Date()){WScript.StdOut.WriteLine(getFullYear()*10000+(getMonth()+1)*100+getDate())};
for /f %%D in ('cscript //nologo //B "%tmpJS%"') do set "YYYYMMDD=%%D"
Wow - that is a very convoluted way to get the current date in a variable.
This is not a direct answer to your question, but I think I can make your life much easier :-)
There really is no need for a temporary batch file. FOR /F could process the output of your temporary JS script directly.
But I have an even easier solution - GetTimeStamp.bat is a hybrid JScript/batch utility that can do nearly any date and time computation on a Windows machine.
The utility is pure script that will run on any modern Windows machine from XP forward - no 3rd party executable required.
Assuming getTimestamp.bat is in your current directory, or better yet, somewhere within your PATH, then the following simple call will define a YYYYMMDD variable containing today's date in YYYYMMDD format:
call getTimeStamp -f {yyyy}{mm}{dd} -r YYYYMMDD
There are a great many options for specifying the base date and time, many options for adding positive or negative offsets to the date and time, many options for formatting the result, and an option to capture the result in a variable. Both input and output can be directly expressed as local time, UTC, or any time zone of your choosing. Full documentation is embedded within the script.
Figured it out:
running cscript on tmp.js led to an error begin put into tmp.bat
call tmp.bat then returned the weird input error because of the error message inside of tmp.bat.
tmp.bat looked like this when editing
Cscript Error: Can't find script engine "JScript" for script "C:\Users\name\Desktop\tmp.js".
That's why calling tmp.bat returned this error message:
Input Error: There is no file extension in "C:\Users\name\Desktop\error:".
The problem ended up being with jscript.dll. It needed to be (re)registered.
regsvr32 %systemroot%\system32\jscript.dll
^Fixed my problem. Thank you all for the help.

Batch incrementation from external file

I have a script who creates new tags in a SVN, and add some files. I want to automate this task so I would like to find some way to do automatically the incrementation for the tags name, from 1.0 to X.0.
I thought about a conf file who would contains "1.0" as a first version number and who would be overwrite at each call to the script. But not sure I can get the "1.0" value from the file and then do an incrementation on it in my script.
Any help would be really appreciate.
Thanks in advance
Don't create a seed configuration file. Instead, let the batch script default to 1.0 if file does not exist.
#echo off
setlocal
set "conf=version.conf"
if not exist "%conf%" (set version=1.0) else (
for /f "usebackq delims=." %%N in ("%conf%") do set /a version=%%N+1
)
set "version=%version%.0"
(echo %version%)>"%conf%"
I'm assuming you will never run this process multiple times in parallel - it can fail if you do run in parallel. Modifications can be made to lock the conf file so you can run in parallel if need be. See the accepted answer to how to check in command line if given file or directory is locked, that it is used by a process? for more info.
Take a look at keywords in Subversion using autoprops.
First, setup subversion to honor keyword expansion
enable-auto-props = yes
[auto-props]
version.txt = svn:keywords=Revision
Then, setup a simple file, let's call it version.txt with the $revision$ keyword and some random content.
$revision$
Random content
Then, in your batch file, recreate the version.txt file with new random content
echo $revision$ >version.txt
echo %random% %date% %time% >>version.txt
and check in this new file every time your batch file is run, so it will become
$revision 32 $
4214 Mon 21/01/2013 15:53:27,62
This way, subversion will keep an accurate version number of all the runs of the batch file, even in multiple clients and simultaneosly.
You might then extract and use the revision number from version.txt with code similar to
for /f "tokens=1,2" %%a in (version.txt) do (
if %%a==$revision (
echo Revision number is %%b
echo do something with %%b, create %%b tag or whatever
)
)
Since you don't say what language you want to use only general remarks can be given:
It certainly is possible to maintain a small 'version' file holding the 'dottet version number', something like 0.2.6 maybe. That files content can be read by any process. You should implement a little collection of methods to split that content into its numerical tokens (major and minor version and the like). Those numerical values can be processed by any mathematical function you like to use. For example you can increment them. Another method would be some 'implode' function that takes the numerical tokens and creates again a 'dottet version number' (now maybe 0.2.7...) and finally you can write that information back into the file. It certainly makes sense to allow an argument that controls which part of the version should be incremented.
Such scheme is not really efficient, but often sufficient.
Note, that such approach will only work if you can guarantee that it is always only a single process to access that version file. Otherwise multiple processes might overwrite each others results which certainly is a cause of problems.
As an alternative, maybe a more elegant alternative, you might consider treating the subversion repository itself as seed storage for your version number: instead of reading a special files content (what if that file is deleted or something else happens?) make a request to the tags folder inside subversion. It should contain all previously tagged versions. So that is precisely the information you want. Take all version numbers, sort them, take the highest one and process it as above.

Resources