Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!

How to? Batch file problem

If you do it, please build both an internal variable %_dlevel for %_cwd, and also a variable function for arbitrary directory or file: %@dlevel[xxx] where xxx is a directory entry, either a directory or a file (with the usual path resolution, including such relative path indicators as .. or .... (1 or 3 levels up from %_cwd, resp.). Naturally the values of %@dlevel[] and %@dlevel[%_cwd] and %_dlevel are to be the same.

BTW, in your sample code, why did you use IF EXIST rather than IF ISFILE?
1. I don't know how to resolve those relative dir names as TCC does (and I don't feel like re-inventing it). @TRUENAME would screw it all up if, for example, you were dealing with a link of any kind.

2. ... because I've been using IF EXIST for 20+ years (an old dog/new tricks thing).
 
BIZARRE.BTM doesn't appear to read the first c:\index.txt file to get the path to the next index.txt file.......and so forth? Because an index.txt file could have any number of lines, and each line can be a directory path to any folder on the c:\ drive. So you would have to read each line of the file in order to find the next index.txt file. So the Problem Statement in post #6 has this requirement.
I'm not looking for a **next** one. I'm finding all of them (at or below the starting directory) and printing them in the order you asked for. I'm ignoring what the index.txt files say. If they describe a binary tree structure then I believe my method works. If they don't describe a tree structure I don't want to deal with it.
 
Vince,
My understanding from the Problem Statement in post 6 is that we need to read the contents of each index.txt file because the paths point to the next index.txt file, then that index.txt file if not empty will have paths that point to the next index.txt.......and so on. So we have to read each line the index.txt file and use the path to find the next file.

Here is my proposed algorithm

A. I need to learn how to read and save files:
  1. open file c:\index.txt
  2. read line 1 and save it to file 1.txt
  3. repeat step 2 for each line until the EOF
Suppose there are 10 lines in c:\index.txt, then after doing steps 1-3 there will be files 1.txt thru 10.txt

B. Next I need to learn how to read a line to change the directory:
  1. Open file 1.txt
  2. Read line 1 in 1.txt (all of these files will have only one line)
  3. Change the directory using this path
  4. Execute steps 1-3 in section A storing each next file to 11.txt, 12.txt,etc.....
C. The steps in section A & B continue until all index.txt files found are EMPTY.

D. After completing sections A-C there may be any number of i.txt files from the above process located in the same folder.
Suppose the process yields 100 files from 1.txt to 100.txt which come from many different directories.
Now we can merge all 100 files into a file named ListFile.txt which will contain 100 lines in REVERSE order
as required in the Problem Statement in post 6.

Note: there should not be a problem with memory overload or memory space because the .txt files are very small.
Even if there are 1000 directories involved there should not be a memory issue.

Is all of the above possible using DOS scripting?
 
Last edited:
Vince,
My understanding from the Problem Statement in post 6 is that we need to read the contents of each index.txt file because the paths point to the next index.txt file, then that index.txt file if not empty will have paths that point to the next index.txt.......and so on. So we have to read each line the index.txt file and use the path to find the next file.

Here is my proposed algorithm

A. I need to learn how to read and save files:
  1. open file c:\index.txt
  2. read line 1 and save it to file 1.txt
  3. repeat step 2 for each line until the EOF
Suppose there are 10 lines in c:\index.txt, then after doing steps 1-3 there will be files 1.txt thru 10.txt

B. Next I need to learn how to read a line to change the directory:
  1. Open file 1.txt
  2. Read line 1 in 1.txt (all of these files will have only one line)
  3. Change the directory using this path
  4. Execute steps 1-3 in section A storing each next file to 11.txt, 12.txt,etc.....
C. The steps in section A & B continue until all index.txt files found are EMPTY.

D. After completing sections A-C there may be any number of i.txt files from the above process located in the same folder.
Suppose the process yields 100 files from 1.txt to 100.txt which come from many different directories.
Now we can merge all 100 files into a file named ListFile.txt which will contain 100 lines in REVERSE order
as required in the Problem Statement in post 6.

Note: there should not be a problem with memory overload or memory space because the .txt files are very small.
Even if there are 1000 directories involved there should not be a memory issue.

Is all of the above possible using DOS scripting?
Please stop saying "DOS". That's possible with a batch file written for TCC. I don't think your algorithm guarantees that the empty ones are together at one end of the list. What if 3.txt and 8.txt point to empty index.txt files? And I don't think your algorithm prevents duplicates. It's hard to get rid of duplicates in a list if they are not consecutive. What if there's a circular reference (c:\a\index.txt mentions c:\b\index.txt and c:\b\index.txt mentions c:\a\index.txt?
 
Steve F. ... would you agree with these?
Code:
p:\4utils\release> echo %@dlevel[c:\]
0

p:\4utils\release> echo %@dlevel[c:\windows]
1

p:\4utils\release> echo %@dlevel[c:\windows\]
1

p:\4utils\release> echo %@dlevel[c:\autoexec.bat]
1

p:\4utils\release> echo %@dlevel[c:\windows\*]
2

p:\4utils\release> echo %@dlevel[c:\windows\explorer.exe]
2

p:\4utils\release> echo %@dlevel[c:\windows\system32\*]
3

p:\4utils\release> echo %@dlevel[c:\*]
1
 
Here is my proposed algorithm

A. I need to learn how to read and save files:
  1. open file c:\index.txt
  2. read line 1 and save it to file 1.txt
  3. repeat step 2 for each line until the EOF
Suppose there are 10 lines in c:\index.txt, then after doing steps 1-3 there will be files 1.txt thru 10.txt

B. Next I need to learn how to read a line to change the directory:
  1. Open file 1.txt
  2. Read line 1 in 1.txt (all of these files will have only one line)
  3. Change the directory using this path
  4. Execute steps 1-3 in section A storing each next file to 11.txt, 12.txt,etc.....
C. The steps in section A & B continue until all index.txt files found are EMPTY.

D. After completing sections A-C there may be any number of i.txt files from the above process located in the same folder.
Suppose the process yields 100 files from 1.txt to 100.txt which come from many different directories.
I forgot to include at this point to use file compare FC to compare of 1.txt to 100.txt to removing duplicates keeping the last ones. Start with the last .txt file and find a duplicate and remove earlier file, then repeat with 2nd to last, etc.

E. Now we can merge all 100 files into a file named ListFile.txt which will contain 100 lines in REVERSE order
as required in the Problem Statement in post 6.

Note: there should not be a problem with memory overload or memory space because the .txt files are very small.
Even if there are 1000 directories involved there should not be a memory issue.

Is all of the above possible using DOS scripting?
I need to use common DOS commands such as {cd, echo, set, if ... else ..., for, goto, findstr, call} to write a batch script.

Can I use TCC to test and debug using common DOS commands ???
 
To test 100 files for duplicates, you will have to run FC.EXE 4,950 times.
TCC implements the commands you mentioned (except for FINDSTR which is actually FINDSTR.EXE, an external executable, not a command). TCC is nearly 100% compatible with Windows's default command processor, CMD.EXE.
 
thanks Vince.
Do you have any examples how to open a file, extract a line and store the line to a file?
With TCC, yes.
Code:
echo %@line[file,0] > file0
echo %@line[file,1] > file1
...
Or maybe all at once ...
Code:
set index=0
do line in @file
    echo %line > file%index
    set /a index+=1
enddo
 
Thanks for the starter.

How would you read line in 1.txt in
order to use it to charge directory and open the
next file?
 
To test 100 files for duplicates, you will have to run FC.EXE 4,950 times.
TCC implements the commands you mentioned (except for FINDSTR which is actually FINDSTR.EXE, an external executable, not a command). TCC is nearly 100% compatible with Windows's default command processor, CMD.EXE.
To test 100 files for duplicates, you will have to run FC.EXE 4,950 times.
TCC implements the commands you mentioned (except for FINDSTR which is actually FINDSTR.EXE, an external executable, not a command). TCC is nearly 100% compatible with Windows's default command processor, CMD.EXE.

I agree 4950 but not sure how to remove duplicates before finding & completing a list of all
the dir paths
 
Thanks for the starter.

How would you read line in 1.txt in
order to use it to charge directory and open the
next file?
The first line in a file is line 0.
Code:
cdd %@line[1.txt,0]
or
Code:
cd %@line[1.txt,0]
Read about the difference between CDD and CD in the help.
Maybe even
Code:
set nextdir=%@line[1.txt,0]
cdd %nextdir
 
echo off
:: Count number of line in c:\index.txt
set file=c:\index.txt
set /a cnt=0
for /f %%a in ('type "%file%"^|find "" /v /c') do set /a cnt=%%a
echo %file% has %cnt% lines

echo %@line[c:\index.txt,0]
echo %@line[c:\index.txt,1]

echo %@line[c:\index.txt,0] > c:\1.txt
echo %@line[c:\index.txt,1] > c:\2.txt

This code works ok in TCC output is:
c:\index.txt has 2 lines
c:\a\index.txt
c:\b\c\index.txt


The same code not working in Windows 7, 64-bit DOS prompt output is wrong:
c:\index.txt has 2 lines
\index.txt,0]
\index.txt,1]

What am I doing wrong between TCC and DOS?

 
TCC has (easily) 4 times the features of CMD.EXE. The function "@line[]" is strictly for TCC; the Windows command prompt doesn't know anything about it. Doing the kinds of things you want to do is difficult (sometimes impossible) with CMD.EXE. That's why folks use TCC/TCMD.
If you want help writing batch files for CMD.EXE you should go to a forum dedicated to that subject; you won't get much of it here.
 
More ...

@line[] is what's called a "variable function". What it expands to depends on the arguments you give it. CMD.EXE has none. TCC has a few hundred and you can add a few hundred more if you use TCC plugins (written by a few talented (modesty!) TCC fans).

TCC also has a few hundred "internal variables" (add plenty more from plugins). CMD has a handful at best.

And TCC has, tens (if not hundreds) of commands (more with plugins) that CMD doesn't have.

As I said before, with TCC you can easily do things which are difficult or impossible with CMD. The whole raison d'etre of TCC (and 4NT before it, and 4DOS before that ... going back to the 1980s) is to let the user do more things and do things more easily than he can do with the built-in Windows (or, long ago, DOS) command interpreter ... while preserving the old (time-honored?) batch syntax.

Oh! Did I mention batch programming logical constructs? DO and IFF alone are reason enough to use TCC.
 
Vince: I agree with most, but not all. Below are your function arguments, followed by your proposed function value first, then my suggestion. However, IMHO the last element of an argument should never include any wildcard, because it does not make it clear whether it is matches a file or a subdirectory in the level N directory, the former of which does not increase the path depth, but the latter does. My concept of the value of this function is the number of CD .. commands required to change the CWD from the argument's directory to the root directory.

Code:
c:\                     0 0
c:\windows              1 1
c:\windows\             1 1
c:\autoexec.bat         1 0
c:\windows\*            2 2
c:\windows\explorer.exe 2 2
c:\windows\system32\*   3 3
c:\*                    1 1
 
Is there an option to configure TCC to limit commands to be compatible with cmd.exe/dos prompt?
I would love to extend it using all TCC capability but I have to be compatible with existing pc's running XP and Windows 7 from the DOS prompt.
 
TCC extensions are cool but when you will lose compatibility unless all pc's have TCC. In the case of using full TCC, couldn't you switch to Visual Basic or Visual C++?
As said this problem I'm working here has to be compatible with normal DOS commands.
 
Vince: I agree with most, but not all. Below are your function arguments, followed by your proposed function value first, then my suggestion. However, IMHO the last element of an argument should never include any wildcard, because it does not make it clear whether it is matches a file or a subdirectory in the level N directory, the former of which does not increase the path depth, but the latter does. My concept of the value of this function is the number of CD .. commands required to change the CWD from the argument's directory to the root directory.
Code:
c:\                     0 0
c:\windows              1 1
c:\windows\             1 1
c:\autoexec.bat         1 0
c:\windows\*            2 2
c:\windows\explorer.exe 2 2
c:\windows\system32\*   3 3
c:\*                    1 1
To me, it's a matter of what something is **IN**. c:\windows, c:\autoexec.bat, and c:\* all refer to things that are **in** c:\, and c:\ is **in** nothing. I am tempted to subtract 1 from every one of my values (or to add 1 to _DLEVEL). That way, when TCC is **in** level N (_DLEVEL) all it sees (DIR, files or directories excepting "." and "..") are other things which are **in** level N. The only question then is "Should being **in** the root be 0 or 1?". If interpretation remains troublesome, I'll just leave @dlevel out.
 
TCC extensions are cool but when you will lose compatibility unless all pc's have TCC. In the case of using full TCC, couldn't you switch to Visual Basic or Visual C++?
As said this problem I'm working here has to be compatible with normal DOS commands.
If you limit yourself to stuff CMD.EXE can handle TCC should run 99+% of it (be sure to check "Duplicate CMD bugs" in the options dialog) and you can use the debugger (which is TCC). If you want help writing batch files for CMD, you'll be better served elsewhere.

I do write in C++. But there's an appropriate tool for everything. The batch language is perfect for what you want to do; I wouldn't dream of writing an EXE to do it. It's just going to be hard(er) if you're stuck with a weak and clumsy tool like CMD.
 
ok I will pursue a solution using the TCC debug capabilities within the scope of running under common DOS commands that run properly under the DOS prompt.
Thanks.
 
To me, it's a matter of what something is **IN**. c:\windows, c:\autoexec.bat, and c:\* all refer to things that are **in** c:\, and c:\ is **in** nothing. I am tempted to subtract 1 from every one of my values (or to add 1 to _DLEVEL). That way, when TCC is **in** level N (_DLEVEL) all it sees (DIR, files or directories excepting "." and "..") are other things which are **in** level N. The only question then is "Should being **in** the root be 0 or 1?". If interpretation remains troublesome, I'll just leave @dlevel out.
My normal inclination is that level 1 is the first level, but almost nothing in the TCC syntax works that way. For consistency with most other reports in TCC I'd suggest the root directory is _dlevel 0, and so is %@dlevel[c:\].
Any object cataloged in the root directory is level 0. If a directory is cataloged in the root, its contents (files and directories alike) have DLEVEL=1, etc. This is consistent with my concept that the directory level of an object is the number of CD .. commands required to change from the directory it is cataloged to the root directory. The question that remains is what is C:\WINDOWS\ equivalent to: C:\WINDOWS (level 0) or C:\WINDOWS\* (level 1). Analogy with C:\ suggests the latter; so does the behavior of @PATH - the trailing backslash implies a higher level.

I trust you intend that %_dlevel and %@dlevel[%_cwd] would be equal.
 
My normal inclination is that level 1 is the first level, but almost nothing in the TCC syntax works that way. For consistency with most other reports in TCC I'd suggest the root directory is _dlevel 0, and so is %@dlevel[c:\].
Any object cataloged in the root directory is level 0. If a directory is cataloged in the root, its contents (files and directories alike) have DLEVEL=1, etc. This is consistent with my concept that the directory level of an object is the number of CD .. commands required to change from the directory it is cataloged to the root directory. The question that remains is what is C:\WINDOWS\ equivalent to: C:\WINDOWS (level 0) or C:\WINDOWS\* (level 1). Analogy with C:\ suggests the latter; so does the behavior of @PATH - the trailing backslash implies a higher level.

I trust you intend that %_dlevel and %@dlevel[%_cwd] would be equal.
"C:\Windows" and C:\Windows\" mean the same thing to me. I like thinking "c:\" is **in** level 0 (along with "d:\" and "\\lucky\share" ... which is of no consequence) and that the numbering should start with 1. But as you pointed out that would seem odd. So I think I'll start with 0 for the things **in** c:\ (files, dirs, TCC itself when CWD is the root). @DLEVEL would report the level the named thing is **in** with the only anomaly being that it would also report 0 for the root itself (though technically not **in** itself). Perhaps I should read some Bertrand Russell.
 
IMHO %@dlevel[c:\] and %@dlevel[c:\windows] should not have the same value (assuming, of course, that c:\windows is a directory). Just because the MS filesystems represent the root directory with a syntax inconsistent with the representation of subdirectories, nevertheless it is a directory. I think each command below should return the same report, regardless of what CWD is:
Code:
echo _dlevel
echo %@dlevel[%_cwd]
echo %@dlevel[%_cwds]
This is inconsistent between files and directories, for files it reports the depth of their parent directory, but for directories it reports the depth of their content. OTOH it is consistent between CWD and specified directories, wihile distinguishing between the root directory and its child directories. Your concept provides consistency between files and directories of the same parent, but inconsistency between the _dlevel variable and the @dlevel function, and it also makes no distinction between the root directory and its children. Alas, total consistency is not possible. Your program, make your choice, and please document it in clear detail as part of the code or directly associated with it in a help file. Tks, Steve.
 
Last edited:
How about
0 c:\ (an anomaly), c:\*, c:\windows, c:\windows\, c:\autoexec.bat
1 c:\windows\*, c:\windows\system32, c:\windows\system32\, c:\windows\explorer.exe
et cetera
 
The "anomaly" prevents disambiguating the root directory from the directories it contains.

Remember, in all MS file systems every directory is cataloged twice: in its parent and in itself (.. and ., resp.); this includes the root directory, but it is its own parent. Hence "cd .." is always valid. IIRC that's not the case in POSIX file systems, though I may be wrong, and cannot test it.

I still prefer the minimum count of "cd .." commands required to reach the path that further repetition of the command does not change. For root it is 0, for any directory in the root 1, etc. But it's your program...
 
How about this?

A directory and its non-directory contents are at the same level (period). That gets rid of the root being anomalous. It puts c:\ and c:\autoexec.bat at level 0, and c:\windows and c:\windows\explorer.exe at level 1. In math terms, a level is closed on the left (top), containing its left end (the directory) and open on the right (bottom), not containing the right-hand ends (subdirectories).

...\dir\subdir will always have a level one more than ...\dir\file.

If I must for dir vs. file, @DLEVEL will fail for anything that doesn't exist.
 
Sounds great!

...\dir\subdir will always have a level one more than ...\dir\file
and this is right because the contents of "subdir" are one level deeper than the contents of "file".

If I must for distinguish dir vs. file, @DLEVEL will fail for anything that doesn't exist.
(strike-out and italics added)
Not a problem. If it does not exist, it has no level; function value of -1 would be a great indicator. Likewise, a wildcard in the argument prevents distinguishing file from directory, so again -1 would be an indicative function value.
 
How about this?

Code:
c:\> :: some that don't make sense
c:\> echo %@dlevel[c:\*]
-1

c:\> echo %@dlevel[c:\autoexec.bat\]
-1

c:\> :: Level 0
c:\> echo %_dlevel
0

c:\> echo %@dlevel[c:\]
0

c:\> echo %@dlevel[c:\autoexec.bat]
0

c:\> echo %@dlevel[c:\windows\..]
0

c:\> :: Level 1
c:\> echo %@dlevel[c:\windows]
1

c:\> echo %@dlevel[c:\windows\]
1

c:\> echo %@dlevel[c:\windows\.]
1

c:\> echo %@dlevel[c:\windows\explorer.exe]
1
 

Similar threads

Back
Top