; UCD.COM ; ; Uwe H. Steinfeld, 12/07/89 ; ; Syntax: UCD [drive:][directory] ; ; Features: - fully replaces and enhances DOS' CD ; - is able to change drive and directory simultaneously ; - does not need a complete path to the target directory, ; searches recursively through the directory tree ; ; Limitation: - if two directories with the D:\ ; same name in the tree exist │ ; only the first will be found. ├─ STATS ; You have to give the name of │ ├─ EXCEL ; the parent directory to go │ │ └──── DATA ; to the desired one, e.g., │ └─ STATG ; to go to the second data │ └──── DATA ; directory on drive D: use ; UCD D:STATG\DATA ; ; Errorlevel: 0 success ; 1 directory not found ; 2 invalid drive include dos.inc ; MASM macros for better readable code directory equ 10000b ; directory attribute text segment assume cs:text, ds:text, es:text org 100h start: jmp ucd Copyright: db '(C) Uwe H. Steinfeld, 12/07/89' SaveDrive db 0, ':\' SaveDir db 64 dup (0),'$' search db 64 dup (0) root db '\', 0 parent db '..', 0 wild db '*.*', 0 msg1 db 'Invalid directory', 0Dh, 0Ah, '$' msg2 db 'Invalid drive', 0Dh, 0Ah, '$' ucd: @GetDrv ; save current drive and path mov SaveDrive,al ; to go back if the search @GetDir SaveDir ; is unsuccessful mov si,81h ; start of command tail mov di,offset search ; ASCIIZ path storage Uc_1: lodsb cmp al,' ' ; skip leading blanks and jz Uc_1 ; tabs in the command tail cmp al,9 jz Uc_1 cmp al,0Dh ; end of command line ? jnz Uc_2 add cs:SaveDrive,'A' ; no cmd line argument, just @DispStr SaveDrive ; display current drive @Exit 0 ; and path and terminate Uc_2: mov dl,al ; save first letter lodsb ; get next cmp al,':' ; drive specified ? jnz Uc_5 ; set new drive and dl,0DFh ; adjust to uppercase sub dl,'A' ; drive A=0, B=1, ... mov ah,0Eh ; set new drive int 21h @GetDrv ; get drive cmp al,dl ; successful changed ? jz Uc_3 @DispStr msg2 ; invalid drive specified @Exit 2 ; exit with errorlevel 2 Uc_3: lodsb ; get next character call ChkEnd ; only new drive given ? jnz Uc_4 @Exit 0 ; done Uc_4: mov dl,al ; save first letter lodsb Uc_5: xchg dl,al ; no drive given, so stosb ; store saved characters xchg al,dl call ChkEnd ; only 1 char on cmd line ? jnz Uc_7 ; target directory only 1 character long, check for '\' and '.' cmp dl,'.' ; was it 'current' dir ? jnz Uc_6 @Exit 0 ; then we're done Uc_6: cmp dl,'\' ; was it root dir ? jnz Uc_8 @ChDir root ; then go to root dir @Exit 0 ; and quit ; more than 1 directory letter so check for '..' Uc_7: cmp al,'.' ; test first character jnz Uc_8 cmp al,dl ; compare to second jnz Uc_8 @ChDir parent ; change to parent directory @Exit 0 ; and exit ; read rest of command tail Uc_8: stosb lodsb ; get the rest of the cmd tail call ChkEnd ; don't care about what comes jnz Uc_8 ; after the first word ; search begins mov di,offset DTAInit ; ptr to start of DTA area @ChDir root ; start in the root directory call tree ; and call the subroutine mov dl,SaveDrive ; if we return here then the mov ah,0Eh ; directory was not found, int 21h ; so restore the starting @ChDir SaveDir ; drive/dir and stop with @DispStr msg1 ; error message @Exit 1 ; tree search (recursively) tree: call setDTA ; set DTA for GetFirst/Next @GetFirst search,directory ; is 'target' subdirectory jc t1 ; of the current dir ? cmp byte ptr[di+15h],directory jnz t1 @ChDir search ; then change to it and @Exit 0 ; exit with success code t1: @GetFirst wild,directory ; look for subdirectories... t2: jc t4 cmp byte ptr[di+15h],directory jnz t3 cmp byte ptr[di+1Eh],'.' ; ... but not '.' or '..' jz t3 mov dx,di ; change directory to add dx,1Eh ; the one found mov ah,3Bh int 21h add di,43 ; increase dta ptr call tree ; and start over @ChDir parent ; come back if not found sub di,43 ; set dta ptr back call setDTA t3: @GetNext ; find next subdirectory jmp t2 t4: ret setDTA: mov dx,di ; set new disk transfer area mov ah,1Ah int 21h ret ChkEnd: cmp al,' ' ; get byte from command line jz ChkRet ; and check for end of cmp al,9 ; line condition jc ChkRet cmp al,0Dh ChkRet: ret DTAInit: ; start of first DTA text ends end start