Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Kill a directory in DOS
#21
(11-30-2023, 06:30 AM)SMcNeill Wrote:
(11-30-2023, 06:07 AM)eoredson Wrote: Hey. I got an idea for the makers of QB64pe:

Maybe you could add a KillDir(Dir$) function!?

That's what RMDIR does for you.  It's just up to you to make certain the directory is empty, or use the function I provided above.
That is some nice code however I have been using the following code to do the same:

Code: (Select All)
Rem The Windows QB64 silent directory delete utility PD 2022.
Rem This code placed into the public domain free BASIC source.
Rem For usage please read Silent.txt which contains disclaimer notes.

' declare library constants.
Const MAX_PATH = 260
Const INVALID_HANDLE_VALUE = -1

' declare library structures.
Type FILETIME
  dwLowDateTime As _Unsigned Long
  dwHighDateTime As _Unsigned Long
End Type

Type SYSTEMTIME
  wYear As Integer
  wMonth As Integer
  wDayOfWeek As Integer
  wDay As Integer
  wHour As Integer
  wMinute As Integer
  wSecond As Integer
  wMilliseconds As Integer
End Type

Type WIN32_FIND_DATAA
  dwFileAttributes As _Unsigned Long
  ftCreationTime As FILETIME
  ftLastAccessTime As FILETIME
  ftLastWriteTime As FILETIME
  nFileSizeHigh As _Unsigned Long
  nFileSizeLow As _Unsigned Long
  dwReserved0 As _Unsigned Long
  dwReserved1 As _Unsigned Long
  cFileName As String * Max_path
  cAlternateFileName As String * 14
End Type

' declare external libraries.
Declare Dynamic Library "kernel32"
  Function DeleteFileA% (F$)
  Function FindFirstFileA~%& (ByVal lpFileName~%&, Byval lpFindFileData~%&)
  Function FindNextFileA& (ByVal hFindFile~%&, Byval lpFindFileData~%&)
  Function FindClose& (ByVal hFindFile~%&)
  Function RemoveDirectoryA% (F$)
End Declare

Declare Library
  Function GetFileAttributes& (f$)
  Function SetFileAttributes& (f$, Byval a&)
End Declare

_Title "DELETE"

Print "Enter directory to delete";: Input G$
If _DirExists(G$) = 0 Then
  Print "Directory not fuund."
  End
End If
Print "Delete directory and all subfolders/files(y/n)?"
Do
  _Limit 100
  x$ = LCase$(InKey$)
  If x$ = "n" Then End
  If x$ = "y" Then Print: Print "OK..": Exit Do
Loop
If Right$(G$, 1) <> "\" Then G$ = G$ + "\"
Call Silentdel_Directories(G$)
If _DirExists(G$) = 0 Then
  Print "Directory deleted."
Else
  Print "Error deleting directory."
End If
End

' subroutine to access subdirectories
Sub Silentdel_Directories (Directory.Search$)
  ' declare subroutine variables
  Dim Attribute As _Unsigned Long
  Dim ASCIIZ As String * 260
  Dim finddata As WIN32_FIND_DATAA
  Dim Wfile.Handle As _Offset

  ' make directory filename
  ASCIIZ = Directory.Search$ + "*.*" + Chr$(0)

  ' start directory search
  Wfile.Handle = FindFirstFileA(_Offset(ASCIIZ), _Offset(finddata))
  If Wfile.Handle <> INVALID_HANDLE_VALUE Then

      ' delete filenames
      Call Silentdel_DeleteFiles(Directory.Search$)

      ' recurse subdirectories
      Do
        ' check directory attribute
        Attribute = finddata.dwFileAttributes

        ' check directory
        If (Attribute And &H10) = &H10 Then

            ' store directory name
            Directory$ = finddata.cFileName
            Directory$ = Left$(Directory$, InStr(Directory$, Chr$(0)) - 1)

            ' store short filename
            If InStr(Directory$, "?") Then
              Directory$ = finddata.cAlternateFileName
              V = InStr(Directory$, Chr$(0))
              If V Then Directory$ = Left$(Directory$, V - 1)
            End If

            ' check directory name
            If Directory$ <> "." And Directory$ <> ".." Then

              ' make next search directory
              Next.Directory$ = Directory.Search$ + Directory$ + "\"

              ' recursively search subdirectories
              Call Silentdel_Directories(Next.Directory$)
            End If
        End If
      Loop While FindNextFileA(Wfile.Handle, _Offset(finddata))
      x = FindClose(Wfile.Handle)
  End If

  ' delete directory
  Call Silentdel_DeleteDirectory(Directory.Search$)
End Sub

' subroutine to delete an empty directory
Sub Silentdel_DeleteDirectory (Directory$)
  ' declare subroutine variables
  Dim ASCIIZ As String * 260

  ' store directory filename
  ASCIIZ = Directory$ + Chr$(0)

  ' change directory attribute
  AttrX& = GetFileAttributes(ASCIIZ)
  AttrX& = AttrX& And Not &H1 ' remove read-only bit
  x = SetFileAttributes&(ASCIIZ, AttrX&)

  ' delete directory
  x = RemoveDirectoryA(ASCIIZ)
End Sub

' subroutine to delete files in a directory
Sub Silentdel_DeleteFiles (Directory$)
  ' declare subroutine variables
  Dim Attribute As _Unsigned Long
  Dim ASCIIZ As String * 260
  Dim ASCIIZ2 As String * 260
  Dim finddata As WIN32_FIND_DATAA
  Dim Wfile.Handle As _Offset

  ' make filename
  ASCIIZ = Directory$ + "*.*" + Chr$(0)

  Wfile.Handle = FindFirstFileA(_Offset(ASCIIZ), _Offset(finddata))
  If Wfile.Handle <> INVALID_HANDLE_VALUE Then

      ' filename loop
      Do
        ' store filename
        Filename$ = finddata.cFileName
        Filename$ = Left$(Filename$, InStr(Filename$, Chr$(0)) - 1)

        ' check filename
        If Filename$ <> "." And Filename$ <> ".." Then
            ' store filename
            ASCIIZ2 = Directory$ + Filename$ + Chr$(0)

            ' change filename attribute
            AttrX& = GetFileAttributes(ASCIIZ2)
            AttrX& = AttrX& And Not &H1 ' remove read-only bit
            x = SetFileAttributes&(ASCIIZ2, AttrX&)

            ' delete long filename
            x = DeleteFileA(ASCIIZ2)

            ' check error and delete 8.3 filename
            If x = 0 Then
              Short.Filename$ = finddata.cAlternateFileName
              V = InStr(Short.Filename$, Chr$(0))
              If V Then Short.Filename$ = Left$(Short.Filename$, V - 1)
              ASCIIZ2 = Directory$ + Short.Filename$ + Chr$(0)

              ' change filename attribute
              AttrX& = GetFileAttributes(ASCIIZ2)
              AttrX& = AttrX& And Not &H1
              x = SetFileAttributes&(ASCIIZ2, AttrX&)

              ' delete short filename
              x = DeleteFileA(ASCIIZ2)
            End If
        End If
      Loop While FindNextFileA(Wfile.Handle, _Offset(finddata))
      x = FindClose(Wfile.Handle)
  End If
End Sub
Reply
#22
I'm with you Terry -- I'm lost.  If he's running QB64, what I shared works fine.  If he's using QB45 then no new command we write will work.  If he's using DosBox-X, as explained, the DELTREE works.

I have no idea what's being asked for here anymore.  Honestly, I think I'm none even trying with this topic.  Sometimes a guy just has to figure out a way for themselves.
Reply
#23
(11-30-2023, 05:03 AM)eoredson Wrote: But it has to be backwards compatible with QB1, QB4, and QB7..

What is "QB1" and "QB7"?

I'm telling the general about someone else that has to be kept away from Linux. Purposely set a really long ridiculous password for him to make sure he could never be "root" user.

But... why is there such a need for a "nuke" directory command built into QB64?

What is one going to do after data loss and he/she realized the wrong directory was nuked?

BTW "deltree" was yet another way M$ purposely spoiled people and started counteracting with making Windows act more like Unix, in response to ongoing complaints that Windows didn't behave "multiuser" enough. Anyway, in Windows Vista and later the operating system would give someone a hard time with trying to eradicate directories, read-only files and what the system thinks are "my" files, unless it's being handled directly by an account with enough elevation.
Reply
#24
Oh but this is only for programs to run inside DOSBOX. (facepalm)

But why does it have to work in QB64 as well? Better stick to floppy disks, Iomega ZIP disks and any platter smaller than 1GB. Anyway QB64 wouldn't work properly inside DOSBOX. Phoenix requires Windows Vista, doesn't it? And DOSBOX was designed to work primarily with 16-bit applications. So those are like two different worlds...

I think backward compatibility with QBasic, as far as supporting archaic commands in MS-DOS, is a red herring. "JOIN" and "SUBST" obviously don't work on Linux with Wine. The other day I had a program crashing on me for using a drive alias: instead of writing it as "Z:\home\user\Documents\somewhere\something.txt" I wanted to write it down as "Y:\something.txt", with the fake drive letter properly being assigned in the global Wine "prefix".

Apparently "RMDIR /S/Q" cannot be done in DOSBOX because the authors of DOSBOX feared the angry, fist-waving users very willing to lose their data LOL. "Let's just leave it out for safety. We have enough people crabbing about security having to do with that arr-eff-option thing."
Reply
#25
Yeah, I just read every post on this thread and I have to agree with Steve and Terry... I am lost and think Eric is confusing QB64 with QuickBasic. To sum up what I've read:

1) QuickBasic <> QB64
2) DOSBOX is unable to run QB64
3) You should write your own function that checks everything first rather than just deleting the directory with zero regard
4) (Not something I've read but something I want to point out) Your WinAPI code is not going to work in DOSBOX
5) I am confused as all Hell as to what you are trying to achieve
Tread on those who tread on you

Reply
#26
Hi, new nerd to thread here.

It could be that OP wants to write the code using QB64 in the IDE, then compile it using the QB45 compiler or such?

I don't know, but if it were me OP, you can check for a command existing first, if it exists run it. That's one way...

This would let you use `rd /s` in modern MS OS and `deltree /Y` in DOSBox, etc. You can use `rm -rf` in Linux/Mac.

- DOSBox: shell command: `deltree /y`
- Windows: shell command: 'rd /s`
- Mac/Linux: shell command: `rm -rf`

Not perfect, but might be easier than managing all this other stuff.

BTW @SMcNeill that `direntry.h` file approach is nice, but is it it not possible to do this natively in QB64? We can't walk a directory contents?

Anyway, the way I would approach this is try to detect what the environment you're running in is.

I found a few threads on Vogons about detecting if running DOSBox and am sharing those:
From: https://www.vogons.org/viewtopic.php?t=14619

This is a DB-INFO.BAT script someone wrote. You can see many ways to detect if running in dosbox here - you wouldn't implement the entire .BAT file of course, just pick one of the options, or a few and concatenate to test the result...

And for detecting other OS you can simply use built-ins like $IF: https://github.com/QB64Official/qb64/wiki/%24if

Hope this helps.

Code: (Select All)
@ echo off

goto Main

rem  +--------------------------------------------------
rem  ! DB-INFO 1.0.2 - Show essential DOSBox configuration
rem  ! info.
rem  !
rem  ! By MiniMax
rem  +--------------------------------------------------

:Usage
echo Usage DB-INFO [ /n ]
echo.
echo where /n indicates which page to view.
echo.
echo.  Page 1 = DOSBox version and mount information.
echo.  Page 2 - DOSBox emulated hardware.
echo.  Page 3 - Directory listing of C:\ and D:\
echo.
echo If no page number is given all 3 pages will be shown.
goto End

:Main

rem Validate that DB-INFO is running inside DOSBox.

if not "%COMSPEC%" == "Z:\COMMAND.COM" goto NotDB
if not exist %COMSPEC% goto NotDB
if not exist Z:\LOADFIX.COM goto NotDB
if not exist Z:\MOUNT.COM goto NotDB

rem Figure out which version of DOSBox this is.

if not exist Z:\KEYB.COM goto else1
    rem Version 0.66 introduced the KEYB.COM program, so we
    rem are running 0.66 or later.

    set CONFIG=66+
goto endif1
:else1
    rem Version 0.65 introduced the CONFIG -GET option.
    rem If the get-operation succeeds, the CONFIG-variable
    rem will be set to something, and we are running 0.65.
    rem If not, we are running 0.63 or earlier.

    set CONFIG=
    config -get sdl output > NUL:
    if not "%CONFIG%" == "" set CONFIG=65
    if    "%CONFIG%" == "" set CONFIG=63-
:endif1

rem Check if only a specific page is requested.

if "%1" == "/1" goto Page1
if "%1" == "/2" goto Page2
if "%1" == "/3" goto Page3

:Page0
echo DB-INFO 1.0.2 - Show essential DOSBox configuration info.
echo.

if "%1" == "/?" goto Usage
goto Page1

:Page1
echo +--------------------------------------------------
echo ! Page 1 - DOSBox version and mounts.
echo +--------------------------------------------------
echo.

if "%CONFIG%" == "63-" echo DOSBox version 0.63 or earlier. Reported DOS version 5.0.
if "%CONFIG%" == "65"  echo DOSBox version 0.65. Reported DOS version 5.0
if "%CONFIG%" == "66+" ver
echo.

mount

if %1 == /1 goto End
echo.
pause

:Page2
echo +--------------------------------------------------
echo ! Page 2 - DOSBox emulated hardware.
echo +--------------------------------------------------
echo.

rem If we are running version 0.63 or earlier, we can only
rem report on the BLASTER and GUS variables.

if "%CONFIG%" == "63-" goto Page2a
goto Page2b

:Page2a
rem  +--------------------------------------------------
rem  ! Page 2a - For DOSBox v.0.63 or earlier.
rem  +--------------------------------------------------

rem  The last attribute (T) of the BLASTER variable can tell us
rem  which type of card we have. We will make a best-effort to
rem  determine the card type.
rem
rem  Type of card: 1=SB 1.5, 2=SB Pro I, 3=SB 2.0, 4=SB Pro II,
rem  6=SB 16, 7=SB AWE32.

set CONFIG=unknown

rem  First check the standard IRQ 7 settings:

if "%BLASTER%" == "A220 I7 D1 T1" set CONFIG=sb1
if "%BLASTER%" == "A220 I7 D1 T2" set CONFIG=sbpro1
if "%BLASTER%" == "A220 I7 D1 T3" set CONFIG=sb2
if "%BLASTER%" == "A220 I7 D1 T4" set CONFIG=sbpro2
if "%BLASTER%" == "A220 I7 D1 T6" set CONFIG=sb16
if "%BLASTER%" == "A220 I7 D1 T7" set CONFIG=sbawe32

rem Version 0.62 and later added the HDMA setting.

if "%BLASTER%" == "A220 I7 D1 H5 T1" set CONFIG=sb1
if "%BLASTER%" == "A220 I7 D1 H5 T2" set CONFIG=sbpro1
if "%BLASTER%" == "A220 I7 D1 H5 T3" set CONFIG=sb2
if "%BLASTER%" == "A220 I7 D1 H5 T4" set CONFIG=sbpro2
if "%BLASTER%" == "A220 I7 D1 H5 T6" set CONFIG=sb16
if "%BLASTER%" == "A220 I7 D1 H5 T7" set CONFIG=sbawe32

rem  Many games wants the SoundBlaster to use IRQ5 so we will
rem  try that too:

if "%BLASTER%" == "A220 I5 D1 T1" set CONFIG=sb1
if "%BLASTER%" == "A220 I5 D1 T2" set CONFIG=sbpro1
if "%BLASTER%" == "A220 I5 D1 T3" set CONFIG=sb2
if "%BLASTER%" == "A220 I5 D1 T4" set CONFIG=sbpro2
if "%BLASTER%" == "A220 I5 D1 T6" set CONFIG=sb16
if "%BLASTER%" == "A220 I5 D1 T7" set CONFIG=sbawe32

rem Version 0.62 and later added the HDMA setting.

if "%BLASTER%" == "A220 I5 D1 H5 T1" set CONFIG=sb1
if "%BLASTER%" == "A220 I5 D1 H5 T2" set CONFIG=sbpro1
if "%BLASTER%" == "A220 I5 D1 H5 T3" set CONFIG=sb2
if "%BLASTER%" == "A220 I5 D1 H5 T4" set CONFIG=sbpro2
if "%BLASTER%" == "A220 I5 D1 H5 T6" set CONFIG=sb16
if "%BLASTER%" == "A220 I5 D1 H5 T7" set CONFIG=sbawe32

if not "%BLASTER%" == ""  echo SBlaster sbtype          = %CONFIG%
if not "%BLASTER%" == ""  echo SBlaster BLASTER          = %BLASTER%

if not "%ULTRASND%" == "" echo GUS      gus              = true
if not "%ULTRASND%" == "" echo GUS      ULTRASND        = %ULTRASND%
if not "%ULTRADIR%" == "" echo GUS      ULTRADIR        = %ULTRADIR%

goto EndP2

:Page2b
rem  +--------------------------------------------------
rem  ! Page 2b - For DOSBox v.0.65 or later.
rem  +--------------------------------------------------

rem Graphics settings (SDL and Render).

config -get sdl output > NUL:
echo SDL      output          = %CONFIG%
config -get sdl fullresolution > NUL:
echo SDL      fullresolution  = %CONFIG%
config -get sdl windowresolution > NUL:
echo SDL      windowresolution = %CONFIG%

config -get render scaler > NUL:
echo Render  scaler          = %CONFIG%

rem Hardware settings (CPU, SoundBlaster, Gravis Ultrasound,
rem and joystick).

config -get dosbox machine > NUL:
echo DOSBox  machine          = %CONFIG%
config -get dosbox memsize > NUL:
echo DOSBox  memsize          = %CONFIG%

config -get cpu core > NUL:
echo CPU      core            = %CONFIG%
config -get cpu cycles > NUL:
echo CPU      cycles          = %CONFIG%

config -get sblaster sbtype > NUL:
echo SBlaster sbtype          = %CONFIG%
if %CONFIG% == none goto endif2
echo SBlaster BLASTER          = %BLASTER%
:endif2

config -get gus gus > NUL:
echo GUS      gus              = %CONFIG%
if %CONFIG% == false goto endif3
echo GUS      ULTRASND        = %ULTRASND%
echo GUS      ULTRADIR        = %ULTRADIR%
:endif3

config -get joystick joysticktype > NUL:
echo Joystick joysticktype    = %CONFIG%
config -get joystick timed > NUL:
echo Joystick timed            = %CONFIG%
config -get joystick buttonwrap > NUL:
echo Joystick buttonwrap      = %CONFIG%

config -get dos xms > NUL:
echo DOS      xms              = %CONFIG%
config -get dos ems > NUL:
echo DOS      ems              = %CONFIG%
config -get dos umb > NUL:
echo DOS      umb              = %CONFIG%

:EndP2
if %1 == /2 goto End
echo.
pause

:Page3
echo +--------------------------------------------------
echo ! Page 3 - Directory listing of C:\ and D:\
echo +--------------------------------------------------
echo.

if not exist C:\. echo Drive C: is not mounted.
if    exist C:\. dir C:\ /w
if    exist C:\. echo.

if not exist D:\. echo Drive D: is not mounted.
if    exist D:\. dir D:\ /w

if %1 == /3 goto End
echo.
pause
goto End

:NotDB
echo.
echo .--------------------------------------------------.
echo ! Error: DB-INFO must be run from *inside* DOSBox! !
echo '--------------------------------------------------'
echo.
pause
goto End

:End
Hope this helps somehow.
grymmjack (gj!)
GitHubYouTube | Soundcloud | 16colo.rs
Reply
#27
Old Skool coding here!

Code: (Select All)
$CONSOLE:ONLY

CONST Test = 1

RD_OldSkool "z:"





SUB RD_OldSkool (Dir$)

    Dir$ = UCASE$(Dir$) 'old skool file names could only be ALL CAPS
    IF RIGHT$(Dir$, 1) <> "\" THEN Dir$ = Dir$ + "\" 'coding this dor windows only.  Make changes as necessary for Linux/Mac slashes and such
    'Note that the UCASE$ line probably won't work with Linux/MAc as well, as they hold uppercase/lowercase to be case specific

    SHELL "cd > TEMP.TXT"
    OPEN "TEMP.TXT" FOR INPUT AS #1
    INPUT #1, Old_Dir$ 'get the old directory name
    CLOSE #1

    CHDIR Dir$ 'change to the specified directory
    SHELL "cd > TEMP.TXT"
    OPEN "TEMP.TXT" FOR INPUT AS #1
    INPUT #1, Verify_Dir$ 'get the changed directory name
    CLOSE #1

    Verify_Dir$ = UCASE$(Verify_Dir$)
    IF RIGHT$(Verify_Dir$, 1) <> "\" THEN Verify_Dir$ = Verify_Dir$ + "\" 'make certain it matchs old skool formatting before verifying

    IF UCASE$(Verify_Dir$) <> Dir$ THEN 'verify that we're in the proper directory now
        PRINT "ERROR: INVALID DIRECTORY!" 'if not, then error and die
        BEEP
        END
    END IF

    SHELL "dir /b /ad > TEMP.TXT"

    OPEN "TEMP.TXT" FOR INPUT AS #1 'can't use BINARY as we're going old skool!
    IF LOF(1) THEN 'If there's any data in that file and it's not just blank
        REDIM DirList(10000) AS STRING 'If you have more than 10,000 directories on an old skool folder, you fail!
        DO
            i = i + 1
            LINE INPUT #1, DirList(i)
        LOOP UNTIL EOF(1)
        REDIM _PRESERVE DirList(i) AS STRING 'free up unused memory in that array of dir lists
    END IF
    CLOSE #1
    FOR j = 1 TO i
        IF DirList(j) <> "." AND DirList(j) <> ".." THEN
            Sub_Dir$ = Dir$ + DirList(j) + "\"
            RD_OldSkool Sub_Dir$
        END IF
    NEXT


    OPEN "TEMP.TXT" FOR OUTPUT AS #1: CLOSE #1 'make certain there's a TEMP.TXT in the file list to clean up automatically
    SHELL "dir /b *.* > TEMP.TXT"
    OPEN "TEMP.TXT" FOR INPUT AS #1
    IF LOF(1) THEN
        DO
            LINE INPUT #1, File$
            PRINT File$, "TEMP.TXT"
            IF File$ <> "TEMP.TXT" THEN 'can't kill our open file!
                IF Test THEN PRINT "Kill: "; File$ ELSE KILL File$
            END IF
        LOOP UNTIL EOF(1)
    END IF
    CLOSE #1
    KILL "TEMP.TXT" 'now kill that file!
    CHDIR Old_Dir$
    FOR i = 65 TO 90
        Test_Dir$ = CHR$(i) + ":\"
        IF Old_Dir$ = Test_Dir$ THEN EXIT SUB
    NEXT
    IF Test THEN PRINT "RMDIR "; Dir$ ELSE RMDIR Dir$
END SUB

I believe every command in this little RD routine works in QB45 and lower.  It also works in QB64 -- well, the Windows version of QB64.  QB45 never ran on Linux or Mac, so it never followed their rules for slashes and filenames and such, so I certainly didn't bother to write this with those particulars in mind.

As before, I left a TEST variable for anyone who just wants to test this out.  (Make it any non-zero value.)  And, as before, I take **ZERO** responsibility if you point it to some folder/drive and erase it off the face of the earth.  Use this at your own risk!  Recursive File/Folder deletion isn't something suitable for most folks to run like this, and this DOES NOT move anything to the Recycle Bin.  This ZAPS things to oblivion, making them lost forever more.  (Unless you want to spend time and effort running some snazzy file recovery software to look for lost data on a drive and restore it.  NOTE -- I WILL NOT HELP WITH ANY RESTORATION NEEDS FOR LOST DATA!!  You have been warned here first, and repeatedly!)
Reply
#28
Quote:- Windows: shell command: 'rd /s`

I dislike insisting like this but also must add "/Q" switch so it just goes ahead and does its thing quietly, and doesn't ask any confirmation. To make it more equal to what has to be done on Linux with "root" permissions.


(11-30-2023, 06:58 AM)mnrvovrfc Wrote: what the system thinks are "my" files,

To clarify for some people, I meant files marked with "system" flag of the file attributes, apart from "archive", "hidden", "read-only"... and "directory". "system" flag assumes "hidden" as well such as "IO.SYS" and "MSDOS.SYS" in root directory which were sometimes a PITA to show in a file manager. But of course regular files do not get "directory" flag. This is for MS-DOS but I don't know if Windows still works in this way.
Reply
#29
Microsoft introduced "Deltree" with MS-DOS 6.0 because quite a few people wanted a command that, like Unix/Linux, could delete entire directories, whether they were empty or not. It is dangerous for MS users because they are usually just pure users. But the command was useful, and still is for “power users” - but Explorer can also do it very quickly.

Attached is a Deltree for Windows 64 and one for 16 bit MS-DOS. Should also work under the DOS box. Deltree64 is clean and works. If one put it in a directory where the path points, you can call it from the command line.

[Image: Deltree-MS-DOS2-2023-11-30.jpg]


Attached Files
.7z   DeltreeX.7z (Size: 48.29 KB / Downloads: 33)
Reply
#30
DosBox-X comes with DelTree.  Well, at least according to their documentation, it does.
Reply




Users browsing this thread: 4 Guest(s)