0

I have a batch script that is writing all files inclusive of path and version number to a TMP file for a physical device. This batch script then writes any lines that demonstrate a file version number greater than a provided variable.

DIRECTORYX := DIRECTORY /NODATE /NOHEADING /NOTRAILING
DIR_OUTPUT_FILENAME = "TOPAS$UTILLOG:" + F$UNIQUE() + ".TMP"
DEVICE = $1$DGA1112
DIRECTORYX 'DEVICE':[000000...]*.*;* /NOSIZE /OUTPUT='DIR_OUTPUT_FILENAME'

At the same time I have files to which I am not interested in being reported back to me. In this case i want to remove any lines that potentially contain this filename (filename.ext;) fromt he TMP file so that the batch script can continue through it and only report files that i dont explicity want to ignore.

How would I go about reading the file while inside a loop using 'IGNORE_FILE' as the variable for the text string to match and remove the associated line of text so that when my batch script proceeds through the file it will not report files requested to be ignored.

Many Thanks for any help

indiv
  • 17,306
  • 6
  • 61
  • 82
Marcus Culver
  • 305
  • 1
  • 4
  • 8
  • Either [f$locate](http://h71000.www7.hp.com/doc/83final/9996/9996pro_107.html) or [f$match_wild](http://h71000.www7.hp.com/doc/83final/9996/9996pro_107.html) should be able to handle the matching. If you want to get fancier you can use [f$parse](http://h71000.www7.hp.com/doc/83final/9996/9996pro_111.html) to pick apart the strings into various components. – HABO Mar 12 '14 at 20:21
  • I'm not sure I understand what you want to achieve. Removing filename.ext from the TMP file seems equivalent to not writing it: directory has an /exclude qualifier. And search has a /match=nor qualifier, which with searching for filename.ext would exclude these files from the search result. – user2116290 Mar 12 '14 at 21:38

2 Answers2

1

Both comments are a great start. Check them carefully. Which OpenVMS version? Something from the last 2 decades?

Just grab and use DFU !

$ define/user sys$output nl:
$ mcr dfu searc/versio=min=200/excl=(*.dat,*.tmp)/form="!AS"/out=tmp.tmp dka0:
$ type tmp.tmp
BUNDY$DKA0:[SYS0.SYSMGR]OPERATOR.LOG;242
BUNDY$DKA0:[SYS0.SYSMGR]ACME$SERVER.LOG;241
BUNDY$DKA0:[SYS0.SYSMGR]LAN$ACP.LOG;241

You could also consider sticking F$SEARCH in a loop and parse out version and other interesting components to implement your excludes....

$
$ type SEARCH_HIGH_VERSION.COM
$ max = 200
$ old = ""
$ IF p1.EQS."" THEN EXIT 16 ! PARAM
$loop:
$ file = F$SEARC(p1)
$ IF file.EQS."" THEN EXIT 99018 ! NMF
$ IF file.EQS.old THEN EXIT 100164 ! Not wild
$ old = file
$ version = F$PARSE(file,,,"VERSION") - ";"
$ IF max.GE.'version' THEN GOTO loop
$ ! IF ... further string tests
$ WRITE SYS$OUTPUT file
$ GOTO LOOP
$
$ @SEARCH_HIGH_VERSION.COM *.*;*
SYS$SYSROOT:[SYSMGR]ACME$SERVER.LOG;241
SYS$SYSROOT:[SYSMGR]LAN$ACP.LOG;241
SYS$SYSROOT:[SYSMGR]OPERATOR.LOG;242
SYS$SYSROOT:[SYSMGR]TMP.TMP;304
SYS$SYSROOT:[SYSMGR]TMP.TMP;303
SYS$SYSROOT:[SYSMGR]TMP.TMP;302
SYS$SYSROOT:[SYSMGR]TMP.TMP;301
SYS$SYSROOT:[SYSMGR]TMP.TMP;300
%RMS-E-NMF, no more files found
$
$ @SEARCH_HIGH_VERSION.COM tmp.tmp
SYS$SYSROOT:[SYSMGR]TMP.TMP;304
%RMS-F-WLD, invalid wildcard operation
$

DFU will probably be 10* faster than DIR DIR will be 10* faster that F$SEARCH, but you'll loose that in the processing.

Good luck! Hein

Hein
  • 1,453
  • 8
  • 8
  • Note, you do NOT want to use PERL globbing for this, as it does a file-header access for each hit (stat). Find::File does not return (multiple) versions. READDIR perhaps yes, but that's work. This works, but as I said it is slow: perl -le "for (<[...]*.*;*>){ $v=$1 if /;(\d+)/; next if $v<200 or /\.tmp/; print}" – Hein Mar 13 '14 at 05:29
  • Hein, Thank you for the code. I've added an exclude clause to the DIR command. However, I have a variable file that provides the main script with node,device and limits. I want to be able to add the exclusions per device (at the moment its on all devices). When gathering the symbol values from the variable file I'm using F$ELEMENT(6, ",", BUFF). How would i write everything from the 7th , to end of line? At the moment it only writes to the next , and thus only tries (and fails) to exclude the first listed file whereas there may be a number of files per device. Thanks for anything in advance – Marcus Culver Mar 13 '14 at 10:00
  • 1
    Well, you are not sharing enough details to allow us to help. Like an example of the variable file. And a disk loop would typically have to go around a file loop perhaps using F$DEVICE as F$SEARCH and DFU only work on 1 device at a time. Admittedly you can give a list to DIR, but that is probably not how this should be used. And... it is beginning to sound an awful lot like work! Happy to give ideas and examples, not happy to do the work :-). – Hein Mar 13 '14 at 15:46
  • Hein, Please see the following pastebin (http://pastebin.com/qSxqWaWY) which has the full script and variable file – Marcus Culver Mar 14 '14 at 10:01
1

Allright... Now I see where you coming from.

How would i write everything from the 7th , to end of line?

Well, you could just loop starting with i=7, or you could use a "quote" the string and use the quote as new separator. Here is an example with both, using a double-quote as almost natural second separator choice

$
$ READ SYS$INPUT BUFF
SHG101,$1$DGA1101:,25,15,10,5000,100,X.TMP,Y.DAT
$
$ excludes = ""
$ tmp = F$ELEMENT(7, ",", BUFF)
$ IF tmp.NES.","
$ THEN
$   i = 8
$   excludes = tmp
$exclude_loop:
$   tmp = F$ELEMENT(i, ",", BUFF)
$   IF tmp.NES.","
$   THEN
$      excludes = excludes + "," + tmp
$      i = i + 1
$      GOTO exclude_loop
$   ENDIF
$   excludes = "/EXCLUDE=(" + excludes + ")"
$ ENDIF
$
$ SHOW SYMB excludes
$
$! Using a different delimitor:
$ READ SYS$INPUT BUFF
SHG101,$1$DGA1101:,25,15,10,5000,100,"X.TMP,Y.DAT"
$
$ excludes = ""
$ tmp = F$ELEMENT(1, """", BUFF)
$ IF tmp.NES."," THEN excludes = "/EXCLUDE=(" + tmp + ")"
$
$ SHOW SYMB excludes

In the code we see: Checking ''DEVICE' for high file versions (>= ;''HVERNO') - may take some time...>

I urge you to check out DFU The big loop code "READ FH3 /END_OF_FILE=LABEL$_EOF_DIRLIST1 BUFF2..." will simplify to:

dfu searc/versio=min=200'excludes'form="!AS"/out=tmp.tmp dka0:

This will run in seconds almost no matter how many files. Toss the whole warning stuff, include it always checking for 32000 as it is (almost) free. After executing the DFU command, create the 'fancy' output if tmp.tmp is not empty by creating your header, and appending tmp.tmp. Always delete tmp.tmp ($ CLOSE/DISP=DELETE )

Free advice...

Those 15 deep nested IF-THEN-ELSE-ENDIF to pick up a message looks terrible (to maintain) Consider an array lookup ?! Here is a worked out example:

$! prep for test
$ EL = p1
$ EL_DIAG = "FILE.DAT"
$ LOCAL_STATUS = "12345"
$
$! Code snippet to be tested
$
$ x  = 'EL'
$ ! Fold multiple conditions into 1 message
$
$ if  (EL .EQ. 7) .OR. (EL .EQ. 14) .OR. (EL .EQ. 21) .OR. (EL .EQ. 25) -
                .OR. (EL .EQ. 29) .OR. (EL .EQ. 30)  THEN x = "L1"
$
$ MSG_6     = "error opening "       + EL_DIAG + " for WRITE (RM=" + LOCAL_STATUS + ")"
$ IDT_6     = "OPENIN"
$ MSG_L1    = "error reading from "  + EL_DIAG + " (RM=" + LOCAL_STATUS + ")"
$ IDT_L1    = "READERR"
$ MSG_8     = "device name missing " + EL_DIAG
$ IDT_8     = "DNNF"
$
$ ! Pick up the required texts
$
$ IF F$TYPE(MSG_'x').EQS.""
$ THEN
$   WRITE SYS$OUTPUT "No message found for code: ", EL
$   EXIT 16
$ ENDIF
$
$ MSG   = MSG_'x
$ IDTXT = IDT_'x
$
$ WRITE SYS$OUTPUT "MSG  : ", MSG
$ WRITE SYS$OUTPUT "IDTXT: ", IDTXT

Cheers, Hein

Hein
  • 1,453
  • 8
  • 8