1.

Solve : Issue with multiple sorts in one dir instance.?

Answer»

Hi All,

I'm not too good on the finer skills of dos, but I did create the following batch file from code scraps:

echo off
setlocal
set srcDir=\\goldals\interfaces$\ZADC\set destdir=\\mbfgoldals\dcsinterfaces$\ZADC\Pickup
set testdir=\\goldals\interfaces$\ZADC\DTS_Pickup\test
set lastmod=
pushd "%srcDir%"
for /f "tokens=*" %%a in ('dir M_??_*.txt /b /od 2^>NUL') do set lastmod=%%a
if "%lastmod%"=="" echo Could not locate files.&GOTO :eof
copy "%lastmod%" "%destDir%"
set lastmod1=
pushd "%srcDir%"
for /f "tokens=*" %%b in ('dir M_A*.txt /b /od 2^>NUL') do set lastmod1=%%b
if "%lastmod1%"=="" echo Could not locate files.&goto :eof
copy "%lastmod1%" "%destDir%"
pushd "%destDir%"
copy /a M*.txt Sales.txt
move M*.txt "%testDir%"


What it does is take the 2 newest dated files (of 2 different types), and concatenates it into a new file.

The issue I have is that there are now multiple files of a type on a certain date, and as such I need to
get the LARGEST SIZED newest dated file.

Thus in this line 
dir M_A*.txt /b /od 2^>NUL
I've tried the sort switches /o:ds, but it only  sorts one instance at a time.

I'm using XP version 5.1.2600 command line.

Is there a way to sort twice in one instance using dir?

Or what is my best solution?

Thanks! :-)
Quote

Is there a way to sort twice in one instance using dir?

No * That is the short answer. DOS is not a full feature database manager.
Yes, if you can explain what you want to do. In plain English.

Do you mean to create a list of ITEMS sorted on two fields?

In COMPUTER program a collection of code fragments is of little value if you do not have an understanding of what they mean. Nd books have been written about how important it is to clearly express thoughts so others may help you.

Please try again. No code, just what you want do.My apologies.

I have a directory with 2 types of text file, those whose names start with M, and those starting with M_A.

On a DAILY basis, I need one of each of these two files concatenated into one new file calles Sales.txt

The criteria to determine the 2 files to use:

1) For each type, on the latest modified date (time not considered.)

2) There will be multiple files on the newest modified date, and so, in addition and for each type, it must be the largest file.

Thus, those in bold needs to be chosen from below example.

Name---Size---Modified
~~~~~~~~~~~~~~~

M1.txt---50---31/10/2010
M2.txt---60---30/10/2010
M3.txt---100 ---29/10/2010
M4.txt---23---30/10/2010
M5.txt--- 77---31/10/2010
M_A1.txt ---45---31/10/2010
M_A2.txt --- 65---30/10/2010
M_A3.txt---89---31/10/2010
M-A4.txt---42---30/10/2010
M_A5.txt---74---31/10/2010

I need to run this procedure from a batch file.
Please help me out with code.That is excellent!
Now we understand the challenge. The only suggestion I would have in your description is to do not use the expression "type" as this may cause confusion. Instead, you have a naming convention for your files. So let's substitute the word "style" in place of the word "type" to make it clear not talking about an actual file type but a naming convention you have chosen .
Reader you mentioned the use of the instance. In some context instance would have a different meaning, so let's drop the use of instance in this case.
So as I understand it, you are looking for two files that conform to your style of naming convention. Both files must be the largest of their style and of the most recent date.
I am not very good at doing one-liners. I would probably break it up into several lines of code and have two FOR loops . One to identify files of the most recent dates for the two forms of your style. Then another loop to determine the largest files for the two forms of your style. At the end of that there should be only two files left that conform to your style. Then the last step would be to simply merge those two files together into your sales report. A personal preference for the sort of thing is to create a list of files and then go through the list and pick out the ones that conform to the criteria and write it to a new list. Then processing the list again and eventually end up with a list that has just the two files in it. It would not be concerned about speed, the text files would be rather small compared to the size of files. Moving files around would get to be much more intensive task. Simply creating a list of all names has very low overhead to the system.

Pardon me for not writing the code for you, I am very limited to what I'm able to do because of my personal handicap. At any time somebody like Salmon and Trout
we'll pop in here and give you a half page of code that works right the first time.

Quote from: Geek-9pm on November 19, 2010, 10:55:28 AM
Salmon and Trout

we are very flattered by your confidence (both of us).
Part of the problem is the example you posted is a mess, with nothing aligned. That can be remedied but then the problem with the sort utility rears it's ugly head. The sort utility supplied with Windows does not allow multiple fields as sort keys (unless contiguous) and you cannot mix sort order (ascending and descending) in the same pass.

VBScript does not have a native sort function. You can however use a disconnected recordset (meaning there is no underlying database) which does have sort capability.

This data was used for testing:

Quote
M1.txt---50---31/10/2010
M2.txt---60---30/10/2010
M3.txt---100 ---29/10/2010
M4.txt---23---30/10/2010
M5.txt--- 77---31/10/2010
M_A1.txt ---45---31/10/2010
M_A2.txt --- 65---30/10/2010
M_A3.txt---89---31/10/2010
M-A4.txt---42---30/10/2010
M_A5.txt---74---31/10/2010


Code: [Select]'On Error Resume Next

Const ForReading = 1
Const MaxCharacters = 255
Const adDouble = 5
Const adDate = 7
Const adVarChar = 200

Set fso = CreateObject("Scripting.FileSystemObject")
Set rs = CreateObject("ADOR.Recordset")
Set objRE = CreateObject("VBScript.RegExp")
objRE.Global     = True
objRE.IgnoreCase = False

rs.Fields.Append "FileType", adVarChar, MaxCharacters
rs.Fields.Append "FileName", adVarChar, MaxCharacters
rs.Fields.Append "FileDate", adDate, MaxCharacters
rs.Fields.Append "FileSize", adDouble, MaxCharacters
rs.Open

Set f = fso.OpenTextFile("C:\Temp\SplitSortCombine.txt", ForReading) 'Change as required

Do Until f.AtEndOfStream
strline = f.ReadLine
With objRE
.pattern = "---"
    strLine = .Replace(strLine, ",")
   
    .Pattern= " "
    strLine = .Replace(strLine, "")
  End With
  strFields = Split(strLine, ",")   
 
rs.AddNew
If Mid(strFields(0), 1, 2) = "M_" Then
rs("FileType") = "A"
Else
rs("FileType") = "B"
End If

rs("FileName") = strFields(0)
rs("FileSize") = CDbl(strFields(1))
rs("FileDate") = strFields(2)
rs.Update
Loop

rs.Sort = "FileType ASC, FileDate DESC, FileSize DESC"
rs.MoveFirst
fileOne = rs.Fields.Item("FileName")

rs.Sort = "FileType DESC, FileDate DESC, FileSize DESC"
rs.MoveFirst
fileTwo = rs.Fields.Item("FileName")

WScript.Echo FileOne, FileTwo

rs.Close
f.Close

Save the script with a vbs extension.

Code: [Select]echo off
::
:: Change the path and label of c:\temp\SplitSortCombine.vbs as required
:: Change the path and label of output.dat as required
::
for /f "tokens=1-2" %%i in ('cscript //nologo c:\temp\SplitSortCombine.vbs') do (
  echo copy %%i+%%j output.dat


Save the script with a bat extension. The batch file will run the vbs script. The vbs script reads the data posted above. The results are on the console showing what the copy command will look like. When you're ready, remove the word echo from this line: echo copy %%i+%%j output.dat. You can change the order of the files by reversing %%i and %%j.

Good luck.
Once the VBScript solution was done, I realized with a little smoke and mirrors this could actually be done with only batch code:

Code: [Select]echo off
setlocal enabledelayedexpansion

for /f "tokens=1-5 delims=-/ " %%i in (c:\temp\splitsortcombine.txt) do (
  set fname=%%i
  set fsize=%%j
  set fdateDD=%%k
  set fdateMM=%%l
  set fdateYY=%%m

  if !fsize! LSS 10 (set fsize=00000!fsize!
    ) else if !fsize! LSS 100 (set fsize=0000!fsize!
    ) else if !fsize! LSS 1000 (set fsize=000!fsize!
    ) else if !fsize! LSS 10000 (set fsize=00!fsize!
    ) else if !fsize! LSS 100000 (set fsize=0!fsize!
  )   
   
  if "!fname:~0,2!" EQU "M_" (echo !fdateYY!!fdateMM!!fdateDD!,!fsize!,!fname! >> A.dat
    ) else (echo !fdateYY!!fdateMM!!fdateDD!,!fsize!,!fname! >> B.dat
  )   
)
 
for /f "tokens=3 delims=," %%i in ('sort A.dat') do (
  set FileOne=%%i
)

:next   
  for /f "tokens=3 delims=," %%i in ('sort B.dat') do (
    set FileTwo=%%i
  )

:next
  del A.dat
  del B.dat
  echo copy %FileOne%+%FileTwo% output.dat

As in the previous post, the results are on the console showing what the copy command will look like. When you're ready, remove the word echo from the last line in the file.

IMO the VBScript is more elegant and easier to read, but hey! that's just me.

Good luck.


Discussion

No Comment Found