sommar@enea.se (Erland Sommarskog) (04/01/88)
There are probably as many ways to move between directories as there are VMS users. Some use SWING with bells and whistles that give. Other uses a CD.COM which emulates cd on Unix. Myself, I am one of those who have a symbol and a logical name for each directory. For instance if I have a directory somewhere called UTILITIES I may have a symbol UTILI*TIES == "CHP DISK:<HOME.SUBDIR.UTILITIES>" (See below on CHP.) And a logical name referring to the directory, which is convenient when I need to refer to it from somewhere else. One good point is that I don't have to remember the exact structure of my directory tree. I have a command file that defines all these names at login time. I also have two command files for creating and deleting directories, automatically updating the command file. This method fails of course when I visit somebody else's directories. for this I use a convenient little directory-tree climber. All these utilities are contained in this posting. Use them if you like. CONTENTS: CHP.COM: Performs a SET DEFAULT and changes the prompt to the directory. Only the lowest directory name is displayed. CREDIR.COM: Creates a new directory, a symbol for going there and a logical name. Adds the two names to the file KOM:KATALOG.COM (you will probably edit CREDIR to use some other name). The directory may already exist, i.e. you can call it just to get the names. DELDIR.COM Deletes (recursively) a directory and removes the names for it. Z.COM: The climber. Example: "Z ,, , po" first takes us to the home directory, goes one step up and then to PO.DIR, if it exists. Else we go to PO*.DIR if PO* is unique. A special feature is that Z looks for concealed device names and translates them if necessary. DOWNSUB.PAS: Performs the same task as Z.COM, but is quicke, they say. I haven't written this one. Don't know if handles concealed names or finds PO.DIR when there is a PO1.DIR too. ---------------------------------------------------------------------- $create/log CHP.COM $deck/dollars="$88033122150226" $! Performs a SET DEFAULT and sets the prompt according to the $! to name of the default directory. Parents are not included $! in the prompt. $ Set def 'p1' $ Directory = f$dir() $ Directory = f$extract(1, f$length(Directory)-2, Directory) + "> " $ i = 0 $loop: $ Subdir = f$element(i, ".", Directory) $ i = i + 1 $ if f$locate(">", Subdir) .eq. f$length(Subdir) then $ goto loop $ set prompt="''Subdir'" $88033122150226 $create/log Z.COM $deck/dollars="$88033122150299" $! Directory-tree climber originally written by Lars Hamren. Modified $! by Erland Sommarskog to handle logical devices. $! Use: @Z P1 P2 ... $! where Pn is a name of a subdirectory or non-ambiguous abbreviation. $! Pn can also be a comma(,) for the parent directory or double-comma(,,) $! for the login directory. Brackets should not be included. $! You must have read permission in a directory when you use abbreviated names. $! $! Assumption: The symbol "Set default" is defined. Preferably it points at a $! DCL routine setting the prompt to the current directory. $! $ Say = "Write sys$output" $ On Error then $ Goto Error $ On Severe then $ Goto Error $ Current = f$directory() $ i = 1 $ Parameter = p1 $Loop: $ If Parameter .nes. "," then $ Goto NotUp $ Set default <-> $ If f$directory() .nes. "<000000>" then $ Goto Endloop $ Disk = f$parse("<>",,,"DEVICE") $ Disk = f$extract(0, f$locate(":", Disk), Disk) $ File_name = f$logical(Disk) $ If File_name .eqs. "" then $ Goto Endloop $ Dot_pos = f$locate(".>", File_name) $ If Dot_pos .eq. f$length(File_name) then - $ Dot_pos = f$locate(".]", File_name) $ If Dot_pos .eq. f$length(File_name) then $ Goto Endloop $ File_name = f$extract(0, Dot_pos, File_name) + - f$extract(Dot_pos + 1, f$length(File_name), File_name) $ Set default 'File_name' $ Goto Endloop $ NotUp: $ If Parameter .nes. ",," then $ Goto NotHome $ Set default sys$login $ Goto Endloop $ NotHome: $ File_name = f$search("''parameter'.dir") $ If File_name .nes. "" then Goto Fixed $ File_name = f$search("''parameter'*.dir") $ If File_name .eqs. "" then $ Goto NoExist $ If f$search("''Parameter'*.dir") .nes. "" then $ Goto NotUnique $ Fixed: $ File_name = f$parse(File_name,,,"NAME") $ Set default <.'File_name'> $ Endloop: $ Say f$logical("SYS$DISK") + f$directory() $ i = 'i' + 1 $ Parameter = p'i' $ If parameter .nes. "" then $ Goto Loop $Fine: $ chp <> $ Exit $! $! Error exits $NoExist: $ Say "No such directory: ''parameter'" $ Say Current $ Set default 'Current' $ Goto Fine $NotUnique: $ Say "Abbreviation not unique ''Parameter'" $ Say Current $ Set default 'Current' $ Goto Fine $Error: $ Set default 'Current' $ Say "Something went wrong. Back to ''Current'" $ Goto Fine $88033122150299 $create/log CREDIR.COM $deck/dollars="$88033122150380" $! This routine creates a sub-directory and creates a logical name $! for it and a symbol for going to the new directory. The two $! definitions are added to a file KOM:KATALOG.COM which we assume $! is called at login. $! $! Use: $! Credir P1 P2 P3 $! P1 = Name of sub-directory without brackets. P1 may already exist. $! P2 = Name of the symbol. Default is P1 with a "*" after the 5th char. $! P3 = Logical name. Default is P1. $! $! Assumptions: $! The file KOM:KATALOG.COM exists $! The symbol CHP is defined to SET DEFAULT or a corresponding routine. $! $! $ If p1 .eqs. "" then $ inquire p1 "Name of the directory? " $ Name := 'p1 $ Name := 'f$extract(0, f$locate(">", f$parse("<>")), f$parse("<>"))'.'Name'> $ Symbol := 'p2 $ If Symbol .eqs. "" then - $ Symbol := 'f$extract(0,5,p1)'*'f$extract(5,f$length(p1),p1)' $ LogName := 'f$extract(0, f$locate(":", p3), p3)' $ If LogName .eqs. "" then $ LogName := 'p1 ! $ Create/directory 'Name' $ Open/write File sys$login:temp.xxx $ Write File "!" $ Write File "$ ''Symbol' == ""'" + "'chp' ''Name'""" $ Write File "$ Assign ''Name' ''LogName'" $ Close File $ @sys$login:temp.xxx $ Append sys$login:temp.xxx kom:katalog.com $ Delete/noconfirm/nolog sys$login:temp.xxx; $88033122150380 $create/log DELDIR.COM $deck/dollars="$88033122150455" $! Deletes a directory and all subdirectories. The entries for the $! the directories in KOM:KATALOG.COM are erased. The user is asked $! the deletion of all encountered directories. $! $! Use: $! Deldir P1 $! P1 = Name of subdirectory to be erased. Brackets should be omitted. $! P2 = Should not be given. Only used for internal recursive calls. $! $! Assumptions: $! The file KOM:KATALOG.COM exists. $! The symbol CHP is defined to SET DEFAULT or a corresponding routine. $! $ Level = p2 $ If Level .eqs. "" then $ Level = 1 $ Directory = p1 $ Dir_file_name = f$parse(Directory + ".DIR") $ Inquire/nopunct Answer "Delete ''Dir_file_name'?" $ If f$extract(0, 1, f$edit(Answer, "TRIM, UPCASE")) .eqs. "N" then exit $ chp <.'Directory'> $More_dirs: $ SubDirectory = f$search("**.dir", Level) $ If SubDirectory .eqs. "" then $ Goto Dirs_ready $ Deldir "''f$parse(SubDirectory, "", "", "NAME")'" "''Level + 1'" $ Goto More_dirs $Dirs_ready: $ Delete/noconfirm/nolog *.*; $ Directorynamn = f$directory() $ chp <-> $ Set prot=O:rwed 'Dir_file_name' $ Delete/noconfirm/log 'Dir_file_name' $ Open/read Dir_file kom:KATALOG.com $ Open/write New_dir_file kom:KATALOG.com $MoreLines: $ Read/end_of_file=EOF Dir_file Line $ If f$locate(Directorynamn, Line) .eq. f$length(Line) then - Write New_dir_file Line $ Goto MoreLines $EOF: $ Close Dir_file $ Close New_dir_file $ Exit $88033122150455 $create/log DOWNSUB.PAS $deck/dollars="$88033122150530" program downsub(output); (* DOWNSUB, a fast way to change subdirectory (emulates DOWNSUB.COM in DNALIB). Should be run as a foreign command and may be given several parameters. $ d ! Show default $ d sub ! Goto subdirectory 'sub' (name may be abbreviated) $ d , ! Go up one level $ d ,, ! Goto home directory Written by : Bengt Larsson E-81 Created : 30/7-1986 Revised : -- *) label 999; (* end of program *) const home_specifier_1 = ',,'; home_specifier_2 = '..'; up_specifier_1 = ','; up_specifier_2 = '.'; type $uword = [word] 0..65535; string_type = varying [255] of char; var line : string_type; find_context : integer := 0; l_bracket,r_bracket : char; start_disk,start_dir : string_type; function sys$setddir ( %stdescr new_dir : packed array [l1..u1:integer] of char := %immed 0; %ref out_len : $uword := %immed 0; %stdescr cur_dir : packed array [l2..u2:integer] of char := %immed 0 ) : integer; extern; function lib$find_file ( %descr file_spec : varying [c1] of char; %descr result_spec : varying [c2] of char; %ref context : integer ) : integer; extern; function lib$get_foreign ( %descr command_line : varying [c] of char ) : integer; extern; function lib$sys_trnlog ( %descr log_name : varying [c1] of char; %ref ret_len : $uword := %immed 0; %descr result : varying [c2] of char; %descr table : varying [c3] of char := 'LNM$DCL_LOGICAL' ) : integer; extern; function lib$set_logical ( %descr log_name : varying [c1] of char; %descr log_value : varying [c2] of char ) : integer; extern; (* --- Remember which brackets we are using --- *) procedure set_brackets; var current_dir : string_type; begin sys$setddir(,current_dir.length,current_dir.body); if index(current_dir,']') <> 0 then begin l_bracket := '['; r_bracket := ']'; end else begin l_bracket := '<'; r_bracket := '>'; end; end; (* set_brackets *) (* --- Find an abbreviated subdirectory and set default to it. --- *) (* --- Also process special parameters for 'sys$login' and 'up' --- *) procedure set_def_dir(dir_abbrev : string_type); var dummy,new_dir,dir_file,home_dir : string_type; pos1,pos2 : integer; begin if (dir_abbrev = home_specifier_1) or (dir_abbrev = home_specifier_2) then begin lib$sys_trnlog('SYS$LOGIN',,home_dir); lib$set_logical('SYS$DISK',substr(home_dir,1,index(home_dir,':'))); sys$setddir('SYS$LOGIN'); sys$setddir(l_bracket + r_bracket); end else if (dir_abbrev = up_specifier_1) or (dir_abbrev = up_specifier_2) then sys$setddir(l_bracket + '-' + r_bracket) else begin if not odd(lib$find_file(dir_abbrev + '*.DIR',dir_file,find_context)) then begin writeln('No such directory : ',dir_abbrev,'*'); writeln(start_disk,start_dir); lib$set_logical('SYS$DISK',start_disk); sys$setddir((start_dir)); goto 999; end; if index(dir_file,dir_abbrev + '.DIR;') = 0 then (* make uniqueness check only if not exact match *) begin if odd(lib$find_file(dir_abbrev + '*.DIR',dummy,find_context)) then begin writeln('Directory abbreviation not unique : ',dir_abbrev,'*'); writeln(start_disk,start_dir); lib$set_logical('SYS$DISK',start_disk); sys$setddir((start_dir)); goto 999; end; end; pos1 := index(dir_file,r_bracket); pos2 := index(dir_file,'.DIR;'); sys$setddir(l_bracket + '.' + substr(dir_file,pos1+1,pos2-pos1-1) + r_bracket); end; end; (* set_def_dir *) (* --- Extract the parameters from the command line and call set_def_dir --- *) procedure process_parameters(line : string_type); var first,last : integer; exit : boolean; new_dir,disk : string_type; begin first := 1; last := 1; while first <= line.length do begin last := first; exit := false; while (last <= line.length) and not exit do if line[last] = ' ' then exit := true else last := last + 1; last := last - 1; set_def_dir(substr(line,first,last-first+1)); sys$setddir(,new_dir.length,new_dir.body); lib$sys_trnlog('SYS$DISK',,disk); writeln(disk,new_dir); first := last + 2; end; end; (* process_parameters *) (* --- Main program. Show current default or process parameters --- *) begin lib$get_foreign(line); set_brackets; lib$sys_trnlog('SYS$DISK',,start_disk); sys$setddir(,start_dir.length,start_dir.body); if line = '' then writeln(start_disk,start_dir) else process_parameters(line); 999: end (* downsub *). $88033122150530 -- Erland Sommarskog ENEA Data, Stockholm sommar@enea.UUCP