1828492 Members
2758 Online
109978 Solutions
New Discussion

Re: DCL array question.

 
BartG
New Member

DCL array question.

Is it possible to add a list of file names generated from a dir command into an array? Could you please provide a short example on how I can do that?

Thank you!
11 REPLIES 11
Craig A Berry
Honored Contributor

Re: DCL array question.

There is no such thing as an array in DCL. You can manipulate lists created with a delimiter using the F$ELEMENT lexical function like so:

$ write sys$output f$element(1,"|","foo|bar|baz")
bar

See HELP LEXICAL F$ELEMENT for more info.

Of course it would help to know more about what you are actually trying to accomplish as the need for an array in DCL may be a red herring in your case. There may be a better way to do what you want in DCL, or DCL may not be the best tool for the job. Here is a one-line Perl program that simply loads up the output of the directory command into an array and then prints it out again with some asterisks sprinkled in, which merely makes the point that arrays are easy in Perl, so if you do really want arrays, use something that has them.

$ perl -e "open F, 'DIRECTORY/NOHEAD/NOTRAIL|';" -
_$ -e "my @a = ; print join qq/***\n/, @a;"
DUA0:[KITS.XPDF-PACKAGES]FREEWARE-AXPVMS-FREETYPE-V0203-4-1.PCSI;1
***
DUA0:[KITS.XPDF-PACKAGES]FREEWARE-AXPVMS-T1LIB-V0501-1-1.PCSI;1
***
DUA0:[KITS.XPDF-PACKAGES]FREEWARE-AXPVMS-XPDF-V0302-0-1.PCSI;1
Hein van den Heuvel
Honored Contributor

Re: DCL array question.

As Craig indicates, you can use lists as arrays, but you could not stash too many filenames in such list.

DCL does have a sort of arrays.
(Associative no less :-).
You make them by using variable as index names.

Call the array "test"
Now just declare the first element to be test_1, the next test_2, but you could also use test_aap, test_mies,...

Next create an index 'i'
Pick up a 'test' array element as:

i=2
value = test_'i

It's all smoke and mirrors, but is can be used where arrays would otherwise be used.

For example, this gets a list of files and reverses them for display:

$i = 0
$first = ""
$search_loop:
$i = i + 1
$file = F$SEARCH(p1)
$IF file.EQS."" THEN goto search_done
$IF i.eq.2 .and. file.EQS.first THEN exit 16
$IF i.eq.1 THEN first = file
$file_'i = file ! Stick into array
$GOTO search_loop
$search_done:
$display_loop:
$i = i - 1
$WRITE sys$output i, " ", file_'i
$IF i.GT.1 THEN GOTO display_loop
$EXIT

One does not need arrays too often in DCL.
What is the real problem you are trying to solve? There may be more elegant (perl :-) solutions.

Cheers,
Hein.
Robert Gezelter
Honored Contributor

Re: DCL array question.

BartG,

As has been noted, DCL does not have arrays. However, there is almost always more than one way to "skin the cat".

On several occasions where I have needed something along the lines of an array, I have used the symbol substitution feature to implement something with semantics similar to an array, to wit:

$ index = 1
$ array_'index' = "A"
$ index = index + 1
$ array_'index' = "B"

$ show symbol array_*

The F$TYPE lexical function can be used to determine if a particular element exists, to wit:

$ if f$type().eqs. "" then write sys$output "Element does not exist"

Also, check the value of CLISYMTBL, which controls the number of entries in the DCL symbol table. Please note that CLISYMTBL is dynamic, so it does not require a reboot.

- Bob Gezelter, http://www.rlgsc.com
BartG
New Member

Re: DCL array question.

Thank you so much for all the input. As you can tell, I'm new to DCL and am trying to do some elementary things :)

Basically, what I'm trying to do is a selective delete of files. I have a directory which contains only a few files which I wish NOT to delete.

What I was wanting to know if possible was to pipe the output of a dir command into a list, and evaluate each file name returned in the list on whether or not to delete based on a seperate list of file names which I wish to keep.

I suppose in this case I could simple write the output of a dir command to a file, then open/read the file and evaluate each file name returned. I was trying to find a better way than creating a seperate file to read through.

I hope that helps explain what I'm trying to do...and thank you so much for the responses.
Hoff
Honored Contributor

Re: DCL array question.

DELETE /EXCLUDE=(list) is one potential approach here.

There are other qualifiers around that allow selection by the creation date and such.

In DCL, a loop is normal for processing files for cases such as this. f$search returns a value, and f$file extracts (just) the filename, and you then decide what to delete. An IF with an .eqs. or other such comparison.

Piping commands and piping output from commands on OpenVMS is less common than on Unix. Unix commands tend to be set up for piping, while OpenVMS tends to have APIs such as f$search and such. And the output isn't necessarily set up for piping, or (in some cases) can change.

If piping is the most comfortable approach for you, you will likely want DIRECTORY /NOHEAD /NOTRAIL /COLUMN=1 here -- assuming your version has that.
Hein van den Heuvel
Honored Contributor

Re: DCL array question.

Here is something along the lines you are looking for. A real solution probably would need to be made much more robust. And you have to wonder what to do with versions or not in the exclude list.

$open/read not 'p1
$read_loop:
$read/end=read_done not record
$name=record - "." - ";" - "$" - "-" ! Hack
$not_'name = 1
$goto read_loop
$read_done:
$close not
$
$show symb not_*
$delete_loop:
$file = f$search("*.*;*")
$if file.eqs."" then exit
$name = f$elem(1,"]",file) - "." - ";" - "$" - "-"
$if "".eqs.f$type(not_'name) then delete 'file
$goto delete_loop

Look at the line identified by ! Hack.
Here we construct the array element, but dcl variable names only may use characters [A-Z0-9_] and [a-z] maps to [A-Z]. Specifically you can not use [.;$\-].

It's a hack only. Why? Weel, it only subtracts 1 dash or dollar but there could be many. It just makes file a.txt equal to at.xt and test.123;4 equal to test.12;34 ... but that would serves you right! (and it happens to be a safe failure :-).
And most importantly it totaly ignored ods-5, full names.

What might a perl solution look like?

perl -ne "chomp; $not{lc($_)}++ }{while (<*.*;*>){unlink unless $not{$_}}" not.txt

Contrary to the DCL version this would handle pretty much all file names.

A better DCL solution would be to create an indexed file with excluded files...
Preperation:

$ rename not.txt [-]not.txt
$ convert/fdl=sys$input/pad=" " [-]not.txt not.txt
file; org indexed;
record; form fixed; size 80
key 0; seg0_l 80

New script (no belt, no suspenders)

$close/nolog not
$open/read not 'p1
$delete_loop:
$file = f$search("*.*;*")
$if file.eqs."" then exit
$name = f$fao("!80AS",f$edit(f$elem(1,"]",file),"LOWERCASE"))
$read/key=&name/error=delete_it not record ! Hmmm, poor name choices :-)
$goto delete_loop
$delete_it:
$delete 'file
$goto delete_loop


If you wanted to try this. Then go to a temp directory and execute:

$create create.com
$set noon
$create A.TMP;1
$create B.TMP;1
$create C.TMP;1
$create D.TMP;1
$create E.TMP;1
$create F.TMP;1
$create G.TMP;1
$create H.TMP;1
Exit
$ create not.txt
not.txt;1
create.com;1
c.tmp;1
Exit
$@create


Enjoy!
Hein.
Hein van den Heuvel
Honored Contributor

Re: DCL array question.

Oh... btw... many more options:

>>> remove the delete protection bit from the files not to be deleted :-).
$SET PROT=(s:re,o:re,g:re,w) keep.this

>>> rename the file to be kept to a sub or side-ways directory, delete all that remain, rename back

>>> Just don't put those files in the vulnerable place! Use logical name to find them readily in a more obscure place.

Hein.

Robert Gezelter
Honored Contributor

Re: DCL array question.

>Basically, what I'm trying to do is a selective
>delete of files. I have a directory which
>contains only a few files which I wish NOT to
>delete.
>
>What I was wanting to know if possible was to
>pipe the output of a dir command into a list,
>and evaluate each file name returned in the
>list on whether or not to delete based on a
>seperate list of file names which I wish to
>keep.

Bart,

Ok, using the DIR command and an intermediate file is one way to do this, but it is not the best way to accomplish the task described.

The F$SEARCH DCL lexical function allows access to the same search mechanisms used by the DIRECTORY command. Thus, there is no need to "pipe the output", as there is no need to design plumbing based on the DIRECTORY command.

A simple loop using F$SEARCH will accomplish the simplest version of this problem.

- Bob Gezelter, http://www.rlgsc.com
John Gillings
Honored Contributor

Re: DCL array question.

>Thus, there is no need to "pipe the
>output", as there is no need to design
>plumbing based on the DIRECTORY command.

Although that's often true, I find piping DIRECTORY output can be very useful, using all the power of the DIRECTORY selection qualifiers, without having to code stuff on the consumption side of the list. Here's a basic example (since I don't want a proliferation of files, I tend to use P1 beginning with # to indicate self recursion, especially for pipes).

For directory streams, I generally use /NOHEAD/NOTRAIL to ensure a single file per line, with full filespec.

$ self=F$PARSE(";",F$ENVIRONMENT("PROCEDURE"))
$ IF F$EXTRACT(0,1,p1).EQS."#"
$ THEN
$ target=p1-"#"
$ GOTO 'target'
$ ENDIF
$
$ PIPE DIRECTORYX/NOHEAD/NOTRAIL 'p1' 'p2' | -
@'self' #FILES SYS$PIPE
$ EXIT
$
$ FILES:
$ OPEN/READ in 'p2'
$ FileLoop:
$ READ/END=EndFiles in rec
$ ! rec contains a full filespec
$ ! do something with it here
$ WRITE SYS$OUTPUT rec
$ GOTO FileLoop
$ EndFiles: CLOSE in
$ EXIT

(also note this procedure can be used to process a file containing a list of files)
A crucible of informative mistakes
BartG
New Member

Re: DCL array question.

This is my first time posting a question on the forum and I have to say the responses have been GREAT! Amidst all the responses I have chosen that the DELETE/EXECLUDE is what will work best for me.

Thanks to everyone who replied. I really appreciate your help.
Jan van den Ende
Honored Contributor

Re: DCL array question.

Bart,

>>>
This is my first time posting a question on the forum
<<<

First: WELCOME

And since it is your first time, may I use this opportunity to show you (or rather point you to) the way to say "Thanks" in this forum:

http://forums1.itrc.hp.com/service/forums/helptips.do?#33

Proost.

Have one on me.

jpe
Don't rust yours pelled jacker to fine doll missed aches.