jaclaz Posted May 7, 2010 Posted May 7, 2010 Honestly, I haven't even figured out how some of those examples work (the author appears to abuse formatting a lot so comments are mingled in with commands and he has a fondness for using debug). Good link though.Honesty for honesty, neither have I. Fact is that the "pure-DOS" batch language is so limited that people over the years invented so many workarounds, mostly using "quirks" or "undocumented side effect of some commands" that is nearly impossible to keep track of them, and often not even to actually understand how they work.You need some act of faith and trust them, or you need to test them one line at the time to understand what happens.jaclaz
Queue Posted May 7, 2010 Posted May 7, 2010 (edited) Ok so, I've refined things some so that environment variable space is much less of an issue and to handle much longer path names. It still can't handle file names that contain spaces. I still haven't tested under XP (or anything besides 98SE); I know my %~n2 check works, but don't know what happens if this batch file is called via a file association (does XP pass a capitalized short file name?).@echo offgoto chk:pthecho %NAME%goto fin:chkif ?%1?==?? goto useif ?%1?==?/auto? goto :verif ?%1?==?[?? goto :prsclsset NAME=%1:addshiftif ?%1?==?? goto pthset NAME=%NAME% %1goto add:verif ?%2?==?? goto useif ?%~n2?==?~n2? goto w9xset NAME=%~n2goto pth:w9xlfnfor onecho ;> "%TEMP%.\BUILDTMP.BAT"if not exist "%TEMP%.\BUILDTMP.BAT" goto usefor %%A in ("%2*") do if not exist "%2.*" copy /Y "%TEMP%.\BUILDTMP.BAT" "%%A.tmp" > nulfor %%A in ("%2*") do choice /S /T:;,1 /C:?%%A; ;BUILDASM.BAT< "%TEMP%.\BUILDTMP.BAT" > "%TEMP%.\BUILDTMP.BAT"for %%A in ("%2*") do if exist "%%A.tmp" del "%%A.tmp"set NAME=:: set PATH=%0\..call "%TEMP%.\BUILDTMP.BAT"del "%TEMP%.\BUILDTMP.BAT"goto pth:prsshiftif ?%0?==?? goto endif ?%0?==?]?? goto endif ?%0?==?\? goto slaif ?%0?==?[?? goto slaif ?%0?==?.? goto perset NAME=%NAME%%0goto prs:pershiftif ?%0?==?? goto endif ?%0?==?]?? goto endif ?%0?==?\? goto slaif ?%0?==?[?? goto slagoto per:slaset NAME=goto prs:useecho Usage: BUILDASM.BAT Project Name:finecho Press any key to exit . . .pause > nulcls:endThe commented out line::: set PATH=%0\..can be uncommented only if you redefine PATH manually, and lets BUILDASM.BAT exist outside of PATH; basically, it's only for if you want BUILDASM.BAT to be in an arbitrary location (not the working directory or in the system PATH) AND if you plan to redefine PATH (which I do in my personal use of this file.As before, the file needs to be named BUILDASM.BAT, or the single reference to BUILDASM.BAT needs to be changed to whatever you want to name the file.There's a little bit of wasteful file writing, but it lets me drastically reduce the length of the string to be parsed by removing the entire path from the string (which was causing limitations).Obviously this has deviated a bit from what Sfor originally asked for help with, but it's been a fun experiment and certainly still has a viable use.Edit - I'm dumb, and forgot %2 is a short file name, so if not exist "%2.*" and del "%2.tmp" are both no good for any file names longer than 8.3. I'm trying really hard to come up with a way to avoid saving %%A from either for loop in an environment variable to save on environment variable space (which is pretty limited at its default size).Queue Edited May 8, 2010 by Queue
jaclaz Posted May 7, 2010 Posted May 7, 2010 (edited) Well, under 2K/XP there is variable expansion already:http://www.msfn.org/board/index.php?showtopic=143572&st=1You don't need anything "fancy", a simple "%~n1" or "%~n2" would do.To get short and long filenames in 2k/Xp you can parse the output of a DIR /X in a FOR loop.jaclazP.S.:Since noone took the hint, I just quickly checked Win95cmd.exe:What about trying the 9x enhanced command processor?http://www.boot-land.net/forums/?showtopic=2392and it DOES have the DIR /X option. Edited May 7, 2010 by jaclaz
Queue Posted May 8, 2010 Posted May 8, 2010 (edited) Check the :ver section; it accomodates %~n2.The dumb fast post option ate my post, so I really don't feel like retyping everything I had. The gist of it was, thanks for the suggestions, and I do have Win95cmd, but the point of this exercise is to accomplish it without using non-default tools (and using default settings, which is why I accomodate limited environment variable space, but don't have a safety for if Command Extensions are off).While I know my %~n2 check works, what I don't know is if, when passed a file name via a file association, if a batch file gets a short or long file name piece from %~n2 on XP.Edit - Currently I'm wrestling with if not exist "%%A.*" in a for loop saying a file doesn't exist when it clearly does.Edit2 - And I realized my problem. %%A.* really doesn't exist due to what my loop is doing. Rather, when %%A changes on the next iteration of the loop, that means the new %%A.* doesn't exist.Edit3 - Edited my previous post to make changes to the for loops. I've made some improvements, but things aren't perfect; with the changes, you can have a really long path, but the file name has to be 8.3 in size for it to work; conversely, longer than 8.3 file names work as long as the path isn't too long. File names still can't have spaces in them.Queue Edited May 8, 2010 by Queue
Fredledingue Posted May 8, 2010 Posted May 8, 2010 I still can't figure out why, in 2010, poeple are still programing scripts in DOS while VBScript exists.VBScript would handle your comandline and your short/long file names in two lines, if it's even necessary at all.
Queue Posted May 8, 2010 Posted May 8, 2010 I still can't figure out why, in 2010, poeple are still programing scripts in DOS while VBScript exists.VBScript would handle your comandline and your short/long file names in two lines, if it's even necessary at all.In my case, it's because it's a fun challenge. The more limited your resources, the more satisfying it is to solve a problem using them.Considering I'm using a batch script to parse out a file name to automate compiling assembly code, and I could've written a simple assembly program to handle everything my batch file does in maybe 5 minutes, and it would use less memory and execute faster, it is a waste, but that's not the point. Instead I've spent a little time over the course of like 3 days refining a batch script that has no built-in string handling, to handle formatting an input string, and it's been a blast.Queue
Queue Posted May 9, 2010 Posted May 9, 2010 Ok, I think I'm nearly done with this. I've solved, I think, any path / file name length issues (within reason), and can deal, decently, with spaces in file names.@echo offgoto chk:pthecho %NAME%goto fin:chkif ?%1?==?? goto useif ?%1?==?/auto? goto :verif ?%1?==?]?? goto :preif ?%1?==?[?? goto :prsclsset NAME=%1:addshiftif ?%1?==?? goto pthset NAME=%NAME% %1goto add:verif ?%2?==?? goto useif ?%~n2?==?~n2? goto w9xset NAME=%~n2goto pth:w9xif not exist "%2" goto uselfnfor ontype nul > "%TEMP%.\BUILDTMP.BAT"if not exist "%TEMP%.\BUILDTMP.BAT" goto usefor %%A in ("%2*") do if not exist "%2.*" copy /Y "%TEMP%.\BUILDTMP.BAT" "%%A.tmp" > nulfor %%A in ("%2*") do %COMSPEC% /C for %%B in ("%%A*") do call %0 ]? %%Bfor %%A in ("%2*") do if exist "%%A.tmp" del "%%A.tmp"set NAME=:: set PATH=%0\..call "%TEMP%.\BUILDTMP.BAT"del "%TEMP%.\BUILDTMP.BAT"goto pth:preclsshiftshiftif ?%0?==?? goto endif ?%1?==?? goto ch0if ?%2?==?? goto ch1if ?%3?==?? goto ch2if ?%4?==?? goto ch3if ?%5?==?? goto ch4if ?%6?==?? goto ch5if ?%7?==?? goto ch6if ?%8?==?? goto ch7if ?%9?==?? goto ch8echo ;|choice /S /T:;,1 /C:?%0*%1*%2*%3*%4*%5*%6*%7*%8*%9; BUILDASM.BAT > "%TEMP%.\BUILDTMP.BAT"goto end:ch8echo ;|choice /S /T:;,1 /C:?%0*%1*%2*%3*%4*%5*%6*%7*%8; BUILDASM.BAT > "%TEMP%.\BUILDTMP.BAT"goto end:ch7echo ;|choice /S /T:;,1 /C:?%0*%1*%2*%3*%4*%5*%6*%7; BUILDASM.BAT > "%TEMP%.\BUILDTMP.BAT"goto end:ch6echo ;|choice /S /T:;,1 /C:?%0*%1*%2*%3*%4*%5*%6; BUILDASM.BAT > "%TEMP%.\BUILDTMP.BAT"goto end:ch5echo ;|choice /S /T:;,1 /C:?%0*%1*%2*%3*%4*%5; BUILDASM.BAT > "%TEMP%.\BUILDTMP.BAT"goto end:ch4echo ;|choice /S /T:;,1 /C:?%0*%1*%2*%3*%4; BUILDASM.BAT > "%TEMP%.\BUILDTMP.BAT"goto end:ch3echo ;|choice /S /T:;,1 /C:?%0*%1*%2*%3; BUILDASM.BAT > "%TEMP%.\BUILDTMP.BAT"goto end:ch2echo ;|choice /S /T:;,1 /C:?%0*%1*%2; BUILDASM.BAT > "%TEMP%.\BUILDTMP.BAT"goto end:ch1echo ;|choice /S /T:;,1 /C:?%0*%1; BUILDASM.BAT > "%TEMP%.\BUILDTMP.BAT"goto end:ch0echo ;|choice /S /T:;,1 /C:?%0; BUILDASM.BAT > "%TEMP%.\BUILDTMP.BAT"goto end:prsshiftif ?%0?==?? goto endif ?%0?==?]?? goto endif ?%0?==?\? goto slaif ?%0?==?[?? goto slaif ?%0?==?.? goto perif ?%0?==?*? goto astset NAME=%NAME%%0goto prs:slaset NAME=goto prs:pershiftif ?%0?==?? goto endif ?%0?==?]?? goto endif ?%0?==?\? goto slaif ?%0?==?[?? goto slagoto per:astset NAME=%NAME% goto prs:useecho Usage: BUILDASM.BAT Project Name:finecho Press any key to exit . . .pause > nulcls:endThe if ?%0?==?*? goto ast line handles spaces in file names, with the flaw of multiple spaces in a row in a file name aren't handled (they'd be compacted down to a single space).Queue
Fredledingue Posted May 9, 2010 Posted May 9, 2010 If it's for fun or for the challenge, it's all right then. I'm also spending cuntless hours designing my own apps, while I don't absolutely need them.
jaclaz Posted May 9, 2010 Posted May 9, 2010 While DEFINITELY not the answer to the ultimate question about DOS batches , I played a bit with a 98 in a VM.A lot of things can be done even without using DEBUG or the "updated command processor":@ECHO OFFREM sh2long.batREM Intended for usage in a WIN98 Command WindowREM Usage:REM sh2long.bat <shortfilename without path but with extension>REM WILL NOT work with spaces in the long file nameCD|CHOICE /N /C:ABCDEFGHIJKLMNOPQRSTUVWXYZ SET CURDRIVE=>ENTER.BATFOR %%A IN (CALL DEL) DO %%A ENTER.BATCD > TEMP.TMPECHO.>> TEMP.TMPTYPE TEMP.TMP | DATE >TEMP.BAT>>ENTER.BAT ECHO SET CURDIR=%%4CALL TEMP.BAT%CURDRIVE%:CD %CURDRIVE%:\CLSDEL ENTER.BATDIR /S /B /Z %1 > TEMP.TMPECHO.>> TEMP.TMPTYPE TEMP.TMP | DATE >TEMP.BAT>>ENTER.BAT ECHO IF NOT "%%4"=="" SET FULLSHORT=%%4CALL TEMP.BATCLSDEL ENTER.BATECHO.DIR /S /B %1 > TEMP.TMPECHO.>> TEMP.TMPTYPE TEMP.TMP | DATE >TEMP.BAT>>ENTER.BAT ECHO IF NOT "%%4"=="" SET FULLLONG=%%4CALL TEMP.BATCLSDEL ENTER.BATECHO.DIR %FULLLONG% | FIND "." > TEMP.TMPECHO.>> TEMP.TMPTYPE TEMP.TMP | DATE >TEMP.BAT>>ENTER.BAT ECHO IF NOT "%%4"=="" SET SHORT=%%4.%%5>>ENTER.BAT ECHO IF NOT "%%4"=="" SET SHORTNAME=%%4>>ENTER.BAT ECHO IF NOT "%%4"=="" SET EXTENSION=%%5>>ENTER.BAT ECHO IF NOT "%%4"=="" SET LONG=%%9>>ENTER.BAT ECHO %%8CALL TEMP.BATCLSCD %CURDIR%ECHO Full Short is %FULLSHORT%ECHO Short is %SHORT%ECHO.ECHO ShortName is %SHORTNAME%ECHO Extension is %EXTENSION%ECHO.ECHO Full Long is %FULLLONG%ECHO Long is %LONG%FOR %%F IN (TEMP.BAT TEMP.TMP ENTER.BAT) DO IF EXIST %%F DEL %%FSET FULLSHORT=SET SHORT=SET SHORTNAME=SET EXTENSION=SET FULLLONG=SET LONG=SET CURDRIVE=SET CURDIR=This should work, as long as the batch is on the SAME drive as the target file.jaclaz
dencorso Posted May 9, 2010 Posted May 9, 2010 ... the answer to the ultimate question about DOS batches [...]42
MDGx Posted May 15, 2010 Posted May 15, 2010 FYI...LFNFOR is an internal batch command, and enables the use of LFNs strictly for the "FOR" batch command.Wikipedia:http://en.wikipedia.org/wiki/COMMAND.COMBATutil (with practical examples):http://users.cybercity.dk/~bse26236/batutil/help/how/VARIOUS.HTM#jerryCan be enabled system-wide every time upon (re)boot [no matter if it is native DOS mode or Windows 9x GUI mode or DOS box/console mode] by adding a line for it in AUTOEXEC.BAT:LFNFOR ONWindows ME users must add it in each separate MS-DOS Configuration File (PIF) shortcut Properties [which makes it available only for that particular DOS box/session/console], since MS removed autoexec.bat + config.sys (boot files) support from WinME.If one cares to restore native DOS mode, autoexec.bat + config.sys support in WinME, please use 1 of these free tools:http://www.mdgx.com/dos.htm#MEHTH
Queue Posted May 15, 2010 Posted May 15, 2010 (edited) I finally took the time to test things out on WinXP and had to make some adjustments. I also added drag&drop support. The script is a bit more skewed towards only working for .asm files, as that's the purpose my batch file was built for.@echo off:: Set project namegoto chk:pthif "%NAME%"=="" goto useif not exist "%NAME%.asm" goto use:: Set compiler pathspath ;path "D:\My Documents\Development\masm32\include"set INCLUDE=%PATH%path ;path "C:\Program Files\Microsoft Visual C++ 6.0 Standard Edition\VC98\LIB"set LIB=%PATH%path ;path "C:\Program Files\Microsoft Visual C++ 6.0 Standard Edition\VC98\BIN":: =======================================================================================:: Put stuff to do to your target file in place of the following three placeholder linescdecho %NAME%goto fin:: .......................................................................................:chkif ?%1?==?? goto useif ?%1?==?]?? goto preif ?%1?==?[?? goto prsif ?%2?==?? if exist %1 goto verclspath ;set NAME=%1if ?%2?==?? goto pthset NAME=%NAME% %2if ?%3?==?? goto pthset NAME=%NAME% %3if ?%4?==?? goto pthset NAME=%NAME% %4if ?%5?==?? goto pthset NAME=%NAME% %5if ?%6?==?? goto pthset NAME=%NAME% %6if ?%7?==?? goto pthset NAME=%NAME% %7if ?%8?==?? goto pthset NAME=%NAME% %8if ?%9?==?? goto pthset NAME=%NAME% %9goto pth:verif "%~n1"=="~n1" goto w9xpath ;set NAME=%~n1if "%NAME%"=="" goto useif not exist "%NAME%.asm" cd /D "%~dp1"goto pth:w9xrem > "%TEMP%.\BUILDTMP.BAT"if not exist "%TEMP%.\BUILDTMP.BAT" goto uselfnfor onfor %%A in (%1*) do if not exist %1.* move /Y "%TEMP%.\BUILDTMP.BAT" "%%A.tmp"for %%A in (%1*) do %COMSPEC% /C for %%B in ("%%A*") do call %0 ]? %%Bfor %%A in (%1*) do if exist "%%A.tmp" del "%%A.tmp"if not exist "%TEMP%.\BUILDTMP.BAT" goto useecho %1| choice /N /C:ABCDEFGHIJKLMNOPQRSTUVWXYZ:\ | set _=for %%A in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [) do if errorlevel H%%A set _=%%Aif ?%_%?==?[? set _=set NAME=call "%TEMP%.\BUILDTMP.BAT" %0del "%TEMP%.\BUILDTMP.BAT"if "%NAME%"=="" goto useif not exist "%NAME%.asm" cd %1\..if not exist "%NAME%.asm" if not ?%_%?==?? %_%:goto pth:: .......................................................................................:preclsshiftshiftif ?%0?==?? goto endif ?%1?==?? goto ch0if ?%2?==?? goto ch1if ?%3?==?? goto ch2if ?%4?==?? goto ch3if ?%5?==?? goto ch4if ?%6?==?? goto ch5if ?%7?==?? goto ch6if ?%8?==?? goto ch7if ?%9?==?? goto ch8echo ;| choice /S /C:?%0*%1*%2*%3*%4*%5*%6*%7*%8*%9; %%1 > "%TEMP%.\BUILDTMP.BAT"goto end:ch8echo ;| choice /S /C:?%0*%1*%2*%3*%4*%5*%6*%7*%8; %%1 > "%TEMP%.\BUILDTMP.BAT"goto end:ch7echo ;| choice /S /C:?%0*%1*%2*%3*%4*%5*%6*%7; %%1 > "%TEMP%.\BUILDTMP.BAT"goto end:ch6echo ;| choice /S /C:?%0*%1*%2*%3*%4*%5*%6; %%1 > "%TEMP%.\BUILDTMP.BAT"goto end:ch5echo ;| choice /S /C:?%0*%1*%2*%3*%4*%5; %%1 > "%TEMP%.\BUILDTMP.BAT"goto end:ch4echo ;| choice /S /C:?%0*%1*%2*%3*%4; %%1 > "%TEMP%.\BUILDTMP.BAT"goto end:ch3echo ;| choice /S /C:?%0*%1*%2*%3; %%1 > "%TEMP%.\BUILDTMP.BAT"goto end:ch2echo ;| choice /S /C:?%0*%1*%2; %%1 > "%TEMP%.\BUILDTMP.BAT"goto end:ch1echo ;| choice /S /C:?%0*%1; %%1 > "%TEMP%.\BUILDTMP.BAT"goto end:ch0echo ;| choice /S /C:?%0; %%1 > "%TEMP%.\BUILDTMP.BAT"goto end:: .......................................................................................:prspath ;:slaset NAME=:chrshiftif ?%0?==?? goto endif ?%0?==?]?? goto endif ?%0?==?\? goto slaif ?%0?==?[?? goto slaif ?%0?==?.? goto perif ?%0?==?*? goto astset NAME=%NAME%%0goto chr:pershiftif ?%0?==?? goto endif ?%0?==?]?? goto endif ?%0?==?\? goto slaif ?%0?==?[?? goto slagoto per:astset NAME=%NAME% goto chr:: .......................................................................................:useecho Usage: BUILDASM.BAT Project Nameecho or: BUILDASM.BAT X:\FOLDER~1\FILENAME.ASMecho or: BUILDASM.BAT "X:\Long Folder Name\Long File Name.asm":finecho Press any key to exit . . .pause | rem | cls:endUnfortunately, cmd.exe is pretty dumb about nesting commands on a single line. For example, pause | cls works fine with command.com, but with cmd.exe, the cls clears the screen during the pause instead of after it, hence why I had to do pause | rem | cls instead. cmd.exe also chokes on path ; | path "drive:\real path" (a nice space saver), so I had to spread out the '':: Set compiler paths'' section a little.In this version I removed any nul redirections; I read that handles opened to devices (nul is a device) aren't closed properly the way file handles are. Whether it's true or not, finding redirection replacements for nul wasn't hard.Queue Edited May 15, 2010 by Queue
loblo Posted September 16, 2014 Posted September 16, 2014 (edited) I've been trying to feed a .BAT script with Long File Names using Send To folder or file association. For some reason Windows 98 sends just the short names, always. Is there a way to force an LFN to be passed through command line parameters. After unsuccessfully trying to do lots of things in the bat files themselves I ended replacing the bat and pif drophandlers in the registry by the windows script host drophandler. From: [HKEY_CLASSES_ROOT\batfile\shellex\DropHandler]@ = "{86C86720-42A0-1069-A2E8-08002B30309D}"[HKEY_CLASSES_ROOT\piffile\shellex\DropHandler]@ = "{86C86720-42A0-1069-A2E8-08002B30309D}" To: [HKEY_CLASSES_ROOT\batfile\shellex\DropHandler]@ = "{60254CA5-953B-11CF-8C96-00AA00B8708C}"[HKEY_CLASSES_ROOT\piffile\shellex\DropHandler]@ = "{60254CA5-953B-11CF-8C96-00AA00B8708C}" Works nicely, now the output of my batch files using %1 arguments is always LFN. However, this would presumably break working with 16bit dos programs that can't handle LFNs but in this case it would be easy to temporarily toggle those values with a couple of registry files. And btw processing multiple files using forfiles.exe from the Win98 resource kit and bat files always results in LFN output regardless of which drop handler is being used. Edited September 16, 2014 by loblo 1
Recommended Posts
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now