Author Topic: Question about using SHELL "dir" on non windows OS.  (Read 9875 times)

0 Members and 1 Guest are viewing this topic.

Offline Dav

  • Forum Resident
  • Posts: 792
    • View Profile
Question about using SHELL "dir" on non windows OS.
« on: January 23, 2021, 01:41:52 pm »
I'm working on a simple file selection box SUB which uses SHELL "dir" calls to get filenames and directory info.  Wanting to make to code compatible with linux and macs, I was wondering what changes if any in the SHELL call I would need to make it work on those OS.  Or would a SHELL "dir" call not work at all on them?  I only can test on Windows right now, not sure about SHELLIng on linux or Mac.  Thanks....

- Dav

Offline odin

  • Administrator
  • Newbie
  • Posts: 92
  • I am.
    • View Profile
Re: Question about using SHELL "dir" on non windows OS.
« Reply #1 on: January 23, 2021, 01:46:33 pm »
Here's how it's done by the IDE, works on all platforms:

Code: QB64: [Select]
  1. FUNCTION idezfilelist$ (path$, method, mask$) 'method0=*.bas, method1=*.*, method2=custom mask
  2.     DIM sep AS STRING * 1
  3.     sep = CHR$(0)
  4.  
  5.     IF os$ = "WIN" THEN
  6.         OPEN ".\internal\temp\files.txt" FOR OUTPUT AS #150: CLOSE #150
  7.         IF method = 0 THEN SHELL _HIDE "dir /b /ON /A-D " + QuotedFilename$(path$) + "\*.bas >.\internal\temp\files.txt"
  8.         IF method = 1 THEN SHELL _HIDE "dir /b /ON /A-D " + QuotedFilename$(path$) + "\*.* >.\internal\temp\files.txt"
  9.         IF method = 2 THEN SHELL _HIDE "dir /b /ON /A-D " + QuotedFilename$(path$) + "\" + QuotedFilename$(mask$) + " >.\internal\temp\files.txt"
  10.         filelist$ = ""
  11.         OPEN ".\internal\temp\files.txt" FOR INPUT AS #150
  12.         DO UNTIL EOF(150)
  13.             LINE INPUT #150, a$
  14.             IF LEN(a$) THEN 'skip blank entries
  15.                 IF filelist$ = "" THEN filelist$ = a$ ELSE filelist$ = filelist$ + sep + a$
  16.             END IF
  17.         LOOP
  18.         CLOSE #150
  19.         idezfilelist$ = filelist$
  20.         EXIT FUNCTION
  21.     END IF
  22.  
  23.     IF os$ = "LNX" THEN
  24.         filelist$ = ""
  25.         IF method = 0 THEN
  26.             FOR i = 1 TO 2
  27.                 OPEN "./internal/temp/files.txt" FOR OUTPUT AS #150: CLOSE #150
  28.                 IF i = 1 THEN SHELL _HIDE "find " + QuotedFilename$(path$) + " -maxdepth 1 -type f -name " + CHR$(34) + "*.bas" + CHR$(34) + " | sort >./internal/temp/files.txt"
  29.                 IF i = 2 THEN SHELL _HIDE "find " + QuotedFilename$(path$) + " -maxdepth 1 -type f -name " + CHR$(34) + "*.BAS" + CHR$(34) + " | sort >./internal/temp/files.txt"
  30.                 GOSUB AddToList
  31.             NEXT
  32.         ELSEIF method = 1 THEN
  33.             SHELL _HIDE "find " + QuotedFilename$(path$) + " -maxdepth 1 -type f -name " + CHR$(34) + "*" + CHR$(34) + " | sort >./internal/temp/files.txt"
  34.             GOSUB AddToList
  35.         ELSEIF method = 2 THEN
  36.             SHELL _HIDE "find " + QuotedFilename$(path$) + " -maxdepth 1 -type f -name " + CHR$(34) + mask$ + CHR$(34) + " | sort >./internal/temp/files.txt"
  37.             GOSUB AddToList
  38.         END IF
  39.         idezfilelist$ = filelist$
  40.         EXIT FUNCTION
  41.  
  42.         AddToList:
  43.         OPEN "./internal/temp/files.txt" FOR INPUT AS #150
  44.         DO UNTIL EOF(150)
  45.             LINE INPUT #150, a$
  46.             IF LEN(a$) = 0 THEN EXIT DO
  47.             FOR x = LEN(a$) TO 1 STEP -1
  48.                 a2$ = MID$(a$, x, 1)
  49.                 IF a2$ = "/" THEN
  50.                     a$ = RIGHT$(a$, LEN(a$) - x)
  51.                     EXIT FOR
  52.                 END IF
  53.             NEXT
  54.             IF filelist$ = "" THEN filelist$ = a$ ELSE filelist$ = filelist$ + sep + a$
  55.         LOOP
  56.         CLOSE #150
  57.         RETURN
  58.     END IF
  59.  
  60.  

Offline Dav

  • Forum Resident
  • Posts: 792
    • View Profile
Re: Question about using SHELL "dir" on non windows OS.
« Reply #2 on: January 23, 2021, 01:50:42 pm »
Thanks, odin!

- Dav

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: Question about using SHELL "dir" on non windows OS.
« Reply #3 on: January 23, 2021, 02:00:16 pm »
That's a time saver, Dav. I could have told you Linux uses the exact same dir command, but that the switches and output format are different than Windows. It's neat to see the QB64 conversions needed to convert that information, which I take means that a SHELL in QB64 will produce the same output format, I would hope, when doing something like SHELL _HIDE "dir *.*>tmp.tmp

So provided the Windows tmp,tmp file appeared in the same format for file names, dates, and file size, and had the same headers, etc. you could rely on one open and read method to extract and parse the info correctly for both platforms. In other words, more is needed than the Windows /b (bare) switch for date and file size info.

As for Mac, it is stated to be POSIX compliant, so I would hope it can be handled the same as Windows for directory output.

Maybe you could make a simple snippet for Fell, who I believe has a Mac and Linux system, and ask him to post the output. If your Windows results match his Linux and Apple results, your golden. That may not even be necessary, but I'd take fact over theory, everyday. (Sorry Bill!).

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Question about using SHELL "dir" on non windows OS.
« Reply #4 on: January 23, 2021, 02:32:29 pm »
There is another cross platform approach that will give you a Directory's List array and a File's list array for a given folder or directory, it happens to be current Best Answer in this thread:
https://www.qb64.org/forum/index.php?topic=1511.msg122368#msg122368

Looks like you will have to parse out the files' string returned by odin's function.

 
« Last Edit: January 23, 2021, 03:45:35 pm by bplus »

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Question about using SHELL "dir" on non windows OS.
« Reply #5 on: January 23, 2021, 02:59:22 pm »
There is another cross platform approach that will give you a Directory's List array and a File's list array for a given folder or directory, it happens to be current Best Answer in this thread:
https://www.qb64.org/forum/index.php?topic=1511.msg122368#msg122368

Looks like you will have to parse out the files' string returned by odin's function.

You might want to attach direntry.h to that post, so folks can find it and download it.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Question about using SHELL "dir" on non windows OS.
« Reply #6 on: January 23, 2021, 03:46:09 pm »
You might want to attach direntry.h to that post, so folks can find it and download it.

OK

Offline Dav

  • Forum Resident
  • Posts: 792
    • View Profile
Re: Question about using SHELL "dir" on non windows OS.
« Reply #7 on: January 23, 2021, 04:23:01 pm »
Thanks for the link, @bplus.  I think I glanced at that once before, but had my interest elsewhere at the time and forgot about it.  Very glad to see it again.  Looks like it's what I'm after.

Here's what I had started working on, was going to add directory info and navigating, and allow a graphics version too.

- Dav

Code: QB64: [Select]
  1.  
  2. a$ = FileSelect$(5, 10, 15, 55, "*.*")
  3.  
  4. IF a$ <> "" THEN
  5.     PRINT "You selected: "; a$
  6.  
  7.  
  8.  
  9. FUNCTION FileSelect$ (y, x, y2, x2, Filespec$)
  10.  
  11.     '=== save original place of cursor
  12.     origy = CSRLIN: origx = POS(1)
  13.  
  14.     '=== Save whole screen
  15.     DIM scr1 AS _MEM, scr2 AS _MEM
  16.     scr1 = _MEMIMAGE(0): scr2 = _MEMNEW(scr1.SIZE)
  17.     _MEMCOPY scr1, scr1.OFFSET, scr1.SIZE TO scr2, scr2.OFFSET
  18.  
  19.     SHELL _HIDE "DIR " + Filespec$ + " /b > $_TeMP_FILE_LIST"
  20.  
  21.     'get list...
  22.     REDIM FileNames$(5000) 'space for 5000 filenames
  23.  
  24.     FF = FREEFILE
  25.     OPEN "$_TeMP_FILE_LIST" FOR INPUT AS #FF
  26.     LineCount = 0
  27.     WHILE ((LineCount < UBOUND(FileNames$)) AND (NOT EOF(FF)))
  28.         LINE INPUT #FF, rl$
  29.         'skip the temp file...
  30.         IF rl$ <> "$_TeMP_FILE_LIST" THEN
  31.             FileNames$(LineCount) = rl$
  32.             LineCount = LineCount + 1
  33.         END IF
  34.     WEND
  35.     CLOSE #FF
  36.  
  37.     KILL "$_TeMP_FILE_LIST"
  38.  
  39.     'draw a box
  40.     COLOR _RGB(100, 100, 255)
  41.     FOR l = 0 TO y2 + 1
  42.         LOCATE y + l, x: PRINT STRING$(x2 + 4, CHR$(219));
  43.     NEXT
  44.  
  45.     DO
  46.  
  47.         FOR l = 0 TO (y2 - 1)
  48.             LOCATE (y + 1) + l, (x + 2)
  49.             IF l + top = Selection THEN
  50.                 COLOR _RGB(0, 0, 0), _RGB(255, 255, 255) 'selected line
  51.             ELSE
  52.                 COLOR _RGB(255, 255, 255), _RGB(0, 0, 0) 'regular
  53.             END IF
  54.             PRINT LEFT$(FileNames$(top + l) + STRING$(x2, " "), x2);
  55.         NEXT
  56.  
  57.         k$ = INKEY$
  58.         SELECT CASE k$
  59.             CASE IS = CHR$(0) + CHR$(72) 'Up arrow
  60.                 IF Selection > 0 THEN Selection = Selection - 1
  61.                 IF Selection < top THEN top = Selection
  62.             CASE IS = CHR$(0) + CHR$(80) 'Down Arrow
  63.                 IF Selection < (LineCount - 1) THEN Selection = Selection + 1
  64.                 IF Selection > (top + (y2 - 2)) THEN top = Selection - y2 + 1
  65.             CASE IS = CHR$(0) + CHR$(73) 'Page up
  66.                 top = top - y2
  67.                 Selection = Selection - y2
  68.                 IF top < 0 THEN top = 0
  69.                 IF Selection < 0 THEN Selection = 0
  70.             CASE IS = CHR$(0) + CHR$(81) 'Page Down
  71.                 top = top + y2
  72.                 Selection = Selection + y2
  73.                 IF top >= LineCount - y2 THEN top = LineCount - y2
  74.                 IF top < 0 THEN top = 0
  75.                 IF Selection >= LineCount THEN Selection = LineCount - 1
  76.             CASE IS = CHR$(0) + CHR$(71) 'Home
  77.                 top = 0: Selection = 0
  78.             CASE IS = CHR$(0) + CHR$(79) 'End
  79.                 Selection = LineCount - 1
  80.                 top = Selection - y2 + 1
  81.                 IF top < 0 THEN top = 0
  82.             CASE IS = CHR$(27) ' ESC cancels
  83.                 FileSelect$ = ""
  84.                 EXIT DO
  85.             CASE IS = CHR$(13) 'Enter
  86.                 FileSelect$ = RTRIM$(FileNames$(Selection))
  87.                 EXIT DO
  88.         END SELECT
  89.     LOOP
  90.  
  91.     _KEYCLEAR
  92.  
  93.     '=== Restore the whole screen
  94.     _MEMCOPY scr2, scr2.OFFSET, scr2.SIZE TO scr1, scr1.OFFSET
  95.     _MEMFREE scr1: _MEMFREE scr2
  96.  
  97.     '=== restore original y,x
  98.     LOCATE origy, origx
  99.  
  100.  
« Last Edit: January 23, 2021, 04:24:15 pm by Dav »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Question about using SHELL "dir" on non windows OS.
« Reply #8 on: January 23, 2021, 04:32:45 pm »
Yeah, I like the fileSpec$ aspect of both odin's and Dav's.

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: Question about using SHELL "dir" on non windows OS.
« Reply #9 on: January 23, 2021, 04:48:07 pm »
Been there, done that, but at some point I'm going to have to add a directory tree to my routine, too. I like to use BINARY instead of INPUT in all my files operations. If you  want to include date an time, let me know; otherwise /b is a nice command line switch to get just the file names. I use it a lot but for files, I like to see when they were created.

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline Dav

  • Forum Resident
  • Posts: 792
    • View Profile
Re: Question about using SHELL "dir" on non windows OS.
« Reply #10 on: January 23, 2021, 06:24:48 pm »
Yeah, I want to show the file info too eventually.  I have API routines to do all that, but was aiming for a cross compatible way.  And seeing how you use SHELL _HIDE often to your advantage kind of motivated me with it.

I planned to get Directories first  (SHELL dir /d), then another call for files, combine both to the Filenames$ array.  Selecting directory name will change to that directory.  Maybe put a ".." selection at the top of the list to go up one directory.  Was thinking that combining SHELL with QB64's builtin directory commands could handle all that, and work on all platforms.

- Dav

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: Question about using SHELL "dir" on non windows OS.
« Reply #11 on: January 23, 2021, 06:43:58 pm »
I'm thinking along the same lines. something like this...

..
[Directory-1]
[Directory-2]
[Directory-3]
Filename1.txt
Filename2.text
Filename3.txt

etc.

Fairly easy to do by making a DIR only call, followed a files only call. add the .., directories, and the files. I track the entry numbers, so all I'll need to know is the entry number that changes from a directory to a file.

In windows there re several options to organize the output. Date of creation, alphabetically, etc. It's a time saver, but in days past I made functions to convert to army time, and sort dates, names, etc. For a list of all switches, visit the easy.dos.com site.

Fun stuff,

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline Dav

  • Forum Resident
  • Posts: 792
    • View Profile
Re: Question about using SHELL "dir" on non windows OS.
« Reply #12 on: January 23, 2021, 06:52:20 pm »
Yes, it's fun to me trying to find workarounds.   I was thinking of just adding the [ ] to the dir names when saving them in the array, and then just strip the [ ] out before using the names to change directories. 

- Dav

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: Question about using SHELL "dir" on non windows OS.
« Reply #13 on: January 23, 2021, 07:05:03 pm »
What I would like, beyond what we are discussing, is a root navigation option. I'm not sure if I'll do that as a second popup, like a right click, or make some sort of flip screen. It's just a whole lot faster to move around to the folders you want to access that way. Of course another option is a dir input line, where you can click somewhere within that line, and it shortens to where you clicked and then displays that directory to the screen like:

c:\QB64\myprograms\

So click anywhere on qb64, and it shortens the url to: c:\qb64, and then opens that directory.

That lateral scrolling routine would make that method quite possible, still, it isn't as fast as with all the opens that Explorer has to offer.

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline Dav

  • Forum Resident
  • Posts: 792
    • View Profile
Re: Question about using SHELL "dir" on non windows OS.
« Reply #14 on: January 25, 2021, 04:15:09 pm »
Here's what I got so far, thanks @Pete for dir command help.  Seems to work ok for me this way. 

Right now it's just for Windows still.  I might make directories a slightly different color.

You can navigate directories, just press enter to enter them.  Enter on filename to select it.

- Dav

Code: QB64: [Select]
  1.  
  2. a$ = FileSelect$(5, 10, 15, 55, "*.*")
  3.  
  4. IF a$ <> "" THEN
  5.     PRINT "You selected: "; a$
  6.  
  7.  
  8.  
  9. FUNCTION FileSelect$ (y, x, y2, x2, Filespec$)
  10.  
  11.     '=== save original place of cursor
  12.     origy = CSRLIN: origx = POS(1)
  13.  
  14.     '=== Save whole screen
  15.     DIM scr1 AS _MEM, scr2 AS _MEM
  16.     scr1 = _MEMIMAGE(0): scr2 = _MEMNEW(scr1.SIZE)
  17.     _MEMCOPY scr1, scr1.OFFSET, scr1.SIZE TO scr2, scr2.OFFSET
  18.  
  19.     loadagain:
  20.     top = 0
  21.     selection = 0
  22.  
  23.     SHELL _HIDE "DIR /b /A:D > $_TeMP_FILE_LIST"
  24.  
  25.     'get list...
  26.     REDIM FileNames$(5000) 'space for 5000 filenames
  27.  
  28.     FileNames$(0) = ".."
  29.  
  30.     FF = FREEFILE
  31.     OPEN "$_TeMP_FILE_LIST" FOR INPUT AS #FF
  32.  
  33.     LineCount = 1
  34.     WHILE ((LineCount < UBOUND(FileNames$)) AND (NOT EOF(FF)))
  35.         LINE INPUT #FF, rl$
  36.         FileNames$(LineCount) = "[" + rl$ + "]"
  37.         LineCount = LineCount + 1
  38.     WEND
  39.     CLOSE #FF
  40.  
  41.     KILL "$_TeMP_FILE_LIST"
  42.  
  43.     SHELL _HIDE "DIR /b /A:-D " + Filespec$ + " > $_TeMP_FILE_LIST"
  44.  
  45.     FF = FREEFILE
  46.     OPEN "$_TeMP_FILE_LIST" FOR INPUT AS #FF
  47.     WHILE ((LineCount < UBOUND(FileNames$)) AND (NOT EOF(FF)))
  48.         LINE INPUT #FF, rl$
  49.         'skip the temp file...
  50.         IF rl$ <> "$_TeMP_FILE_LIST" THEN
  51.             FileNames$(LineCount) = rl$
  52.             LineCount = LineCount + 1
  53.         END IF
  54.     WEND
  55.     CLOSE #FF
  56.  
  57.     KILL "$_TeMP_FILE_LIST"
  58.  
  59.     'draw a box
  60.     COLOR _RGB(100, 100, 255)
  61.     FOR l = 0 TO y2 + 1
  62.         LOCATE y + l, x: PRINT STRING$(x2 + 4, CHR$(219));
  63.     NEXT
  64.  
  65.     DO
  66.  
  67.         FOR l = 0 TO (y2 - 1)
  68.             LOCATE (y + 1) + l, (x + 2)
  69.             IF l + top = selection THEN
  70.                 COLOR _RGB(0, 0, 0), _RGB(255, 255, 255) 'selected line
  71.             ELSE
  72.                 COLOR _RGB(255, 255, 255), _RGB(0, 0, 0) 'regular
  73.             END IF
  74.             PRINT LEFT$(FileNames$(top + l) + STRING$(x2, " "), x2);
  75.         NEXT
  76.  
  77.         k$ = INKEY$
  78.         SELECT CASE k$
  79.             CASE IS = CHR$(0) + CHR$(72) 'Up arrow
  80.                 IF selection > 0 THEN selection = selection - 1
  81.                 IF selection < top THEN top = selection
  82.             CASE IS = CHR$(0) + CHR$(80) 'Down Arrow
  83.                 IF selection < (LineCount - 1) THEN selection = selection + 1
  84.                 IF selection > (top + (y2 - 2)) THEN top = selection - y2 + 1
  85.             CASE IS = CHR$(0) + CHR$(73) 'Page up
  86.                 top = top - y2
  87.                 selection = selection - y2
  88.                 IF top < 0 THEN top = 0
  89.                 IF selection < 0 THEN selection = 0
  90.             CASE IS = CHR$(0) + CHR$(81) 'Page Down
  91.                 top = top + y2
  92.                 selection = selection + y2
  93.                 IF top >= LineCount - y2 THEN top = LineCount - y2
  94.                 IF top < 0 THEN top = 0
  95.                 IF selection >= LineCount THEN selection = LineCount - 1
  96.             CASE IS = CHR$(0) + CHR$(71) 'Home
  97.                 top = 0: selection = 0
  98.             CASE IS = CHR$(0) + CHR$(79) 'End
  99.                 selection = LineCount - 1
  100.                 top = selection - y2 + 1
  101.                 IF top < 0 THEN top = 0
  102.             CASE IS = CHR$(27) ' ESC cancels
  103.                 FileSelect$ = ""
  104.                 EXIT DO
  105.             CASE IS = CHR$(13) 'Enter
  106.                 'go up one dir
  107.                 IF RTRIM$(FileNames$(selection)) = ".." THEN
  108.                     cd$ = _CWD$
  109.                     cd$ = LEFT$(cd$, _INSTRREV(cd$, "\"))
  110.                     CHDIR cd$
  111.                     ERASE FileNames$
  112.                     GOTO loadagain
  113.                 END IF
  114.                 'see if directory
  115.                 test$ = RTRIM$(FileNames$(selection))
  116.                 IF LEFT$(test$, 1) = "[" THEN
  117.                     test$ = MID$(test$, 2, LEN(test$) - 2)
  118.                     CHDIR test$
  119.                     ERASE FileNames$
  120.                     GOTO loadagain
  121.                 ELSE
  122.                     IF RIGHT$(_CWD$, 1) = "\" THEN
  123.                         c$ = _CWD$
  124.                     ELSE
  125.                         c$ = _CWD$ + "\"
  126.                     END IF
  127.                     FileSelect$ = c$ + RTRIM$(FileNames$(selection))
  128.                     EXIT DO
  129.                 END IF
  130.         END SELECT
  131.     LOOP
  132.  
  133.     _KEYCLEAR
  134.  
  135.     '=== Restore the whole screen
  136.     _MEMCOPY scr2, scr2.OFFSET, scr2.SIZE TO scr1, scr1.OFFSET
  137.     _MEMFREE scr1: _MEMFREE scr2
  138.  
  139.     '=== restore original y,x
  140.     LOCATE origy, origx
  141.  
  142.  
« Last Edit: January 25, 2021, 04:18:04 pm by Dav »