:Namespace Files ⎕IO ⎕ML←1 0 ∇ u←uniVer ⍝ Unicode Version? u←80∊⎕DR'' ∇ A←{⍺,'A*'[⎕io+uniVer],⍵} ⍝ use A or * in ⎕NA statements ∇ r←text AppendText name;tn ⍝ Append text to existing file (must be single byte text) tn←name ⎕NTIE 0 r←text ⎕NAPPEND tn(⎕DR' ') ⎕NUNTIE tn ∇ ∇ {protect}Copy FmTo;CopyFileX;GetLastError ⍝ Copy file Fm -> To :If 0=⎕NC'protect' ⍝ Copy fails if and 'To' exists. protect←0 ⍝ Default unprotected copy. :EndIf 'CopyFileX'⎕NA'I kernel32.C32CopyFile'A' <0T <0T I' :If 0=CopyFileX FmTo,protect ⎕NA'I4 kernel32.C32|GetLastError' 11 ⎕SIGNAL⍨'CopyFile error:',⍕GetLastError :EndIf ∇ ∇ Delete name;DeleteFileX;GetLastError 'DeleteFileX'⎕NA'I kernel32.C32DeleteFile'A' <0T' :If 0=DeleteFileX⊂name ⎕NA'I4 kernel32.C32|GetLastError' 11 ⎕SIGNAL⍨'DeleteFile error:',⍕GetLastError :EndIf ∇ ∇ rslt←{amsk}Dir path;handle;next;ok;⎕IO;attrs;FindFirstFileX;FindNextFileX;FindClose;FileTimeToLocalFileTime;FileTimeToSystemTime;GetLastError ⍝ Amsk is a 32 element bool attribute mask. ⍝ Only files with attributes corresponding to 1-s in the mask will be returned. ⍝ '*'s mark default attribute mask. ⍝ ⍝ * [31] <=> READONLY ⍝ [30] <=> HIDDEN ⍝ * [29] <=> SYSTEM ⍝ [28] <=> undocumented ⍝ * [27] <=> DIRECTORY ⍝ * [26] <=> ARCHIVE ⍝ [25] <=> DEVICE ⍝ * [24] <=> NORMAL - only set if no other bits are set ⍝ * [23] <=> TEMPORARY ⍝ * [22] <=> SPARSE FILE ⍝ * [21] <=> REPARSE POINT ⍝ * [20] <=> COMPRESSED ⍝ * [19] <=> OFFLINE ⍝ * [18] <=> NOT CONTENT INDEXED ⍝ * [17] <=> ENCRYPTED ⍝ * rest <=> undocumented (but in the default set so that ⍝ Microsoft can extend them) ⍝ rslt is a vector of character vectors of filenames ⎕IO←0 :If 0=⎕NC'amsk' amsk←~(⍳32)∊30 28 25 ⍝ Default attribute mask. :EndIf _FindDefine handle rslt←_FindFirstFile path :If 0=handle ('ntdir error:',⍕rslt)⎕SIGNAL 102 ⍝ file not found :EndIf rslt←,⊂rslt :While 1=0⊃ok next←_FindNextFile handle rslt,←⊂next :EndWhile :If 0 18∨.≠ok next ('ntdir error:',⍕next)⎕SIGNAL 11 ⍝ DOMAIN :EndIf ok←FindClose handle rslt←↓[0]↑rslt attrs←(32⍴2)⊤0⊃rslt ⍝ Get attributes into bits rslt←(amsk∧.≥attrs)⌿6⊃rslt ⍝ bin unwanted files and info ∇ ∇ rslt←{amsk}DirX path;handle;next;ok;attrs;⎕IO;FindFirstFileX;FindNextFileX;FindClose;FileTimeToLocalFileTime;FileTimeToSystemTime;GetLastError ⍝ Amsk is a 32 element bool attribute mask. ⍝ Only files with attributes corresponding to 1-s in the mask will be returned. ⍝ Amsk defaults to all attributes. ⍝ 0⊃rslt <=> 32 column boolean matrix of attribute bits ⍝ [;31] <=> READONLY ⍝ [;30] <=> HIDDEN ⍝ [;29] <=> SYSTEM ⍝ [;28] <=> undocumented ⍝ [;27] <=> DIRECTORY ⍝ [;26] <=> ARCHIVE ⍝ [;25] <=> undocumented ⍝ [;24] <=> NORMAL - only set if no other bits are set ⍝ [;23] <=> TEMPORARY ⍝ [;22] <=> SPARSE FILE ⍝ [;21] <=> REPARSE POINT ⍝ [;20] <=> COMPRESSED ⍝ [;19] <=> OFFLINE ⍝ [;18] <=> NOT CONTENT INDEXED ⍝ [;17] <=> ENCRYPTED ⍝ rest <=> undocumented ⍝ 1⊃rslt <=> 7 column numeric matrix expressing the file creation time in ⎕TS format ⍝ if the file system does not support this then all columns are 0 ⍝ 2⊃rslt <=> 7 column numeric matrix expressing the file last access time in ⎕TS format ⍝ if the file system does not support this then all columns are 0 ⍝ 3⊃rslt <=> 7 column numeric matrix expressing the file last write time in ⎕TS format ⍝ 4⊃rslt <=> numeric vector giving the file size accurate up to 53 bits ⍝ 5⊃rslt <=> vector of character vectors giving the file names ⍝ 6⊃rslt <=> vector of character vectors giving the 8.3 file name for file systems ⍝ where it is appropriate and different from the file name ⎕IO←0 :If 0=⎕NC'amsk' amsk←32⍴1 :EndIf _FindDefine handle rslt←_FindFirstFile path :If 0=handle ('ntdir error:',⍕rslt)⎕SIGNAL 102 ⍝ file not found :EndIf rslt←,⊂rslt :While 1=0⊃ok next←_FindNextFile handle rslt,←⊂next :EndWhile :If 0 18∨.≠ok next ('ntdir error:',⍕next)⎕SIGNAL 11 ⍝ DOMAIN :EndIf ok←FindClose handle rslt←↓[0]↑rslt (0⊃rslt)←⍉attrs←(32⍴2)⊤0⊃rslt ⍝ Get attributes into bits rslt←(amsk∧.≥attrs)∘⌿¨rslt ⍝ bin unwanted files and info rslt[1 2 3]←↑¨_Filetime_to_TS¨¨rslt[1 2 3] ⍝ put times into ⎕ts format (4⊃rslt)←0(2*32)⊥⍉↑4⊃rslt ⍝ combine size elements rslt/⍨←5≠⍳8 ⍝ bin the reserved elements ∇ ∇ r←Exists name ⍝ Does file exist? r←1 :Trap 19 22 ⋄ ⎕NUNTIE name ⎕NTIE 0 :Else ⋄ r←0 :EndTrap ∇ ∇ r←GetCurrentDirectory;GCD;GetLastError ⍝ Get Current Directory using Win32 API 'GCD'⎕NA'I kernel32.C32GetCurrentDirectory'A' I4 >0T' :If 0≠1⊃r←GCD 256 256 r←2⊃r :Else ⎕NA'I4 kernel32.C32|GetLastError' 11 ⎕SIGNAL⍨'GetCurrentDirectory error:',⍕GetLastError :EndIf ∇ ∇ r←GetText name;tn ⍝ Read a text file as single byte text tn←name ⎕NTIE 0 r←⎕NREAD tn(⎕DR' ')(⎕NSIZE tn) ⎕NUNTIE tn ∇ ∇ MkDir path;CreateDirectoryA;GetLastError;err;CD ⍝ Create a folder using Win32 API 'CD'⎕NA'I kernel32.C32|CreateDirectory'A' <0T I4' ⍝ Try for best function →(0≠CD path 0)⍴0 ⍝ 0 means "default security attributes" ⎕NA'I4 kernel32.C32|GetLastError' err ⎕SIGNAL⍨'CreateDirectory error:',⍕err←GetLastError ∇ ∇ Move filenames;MoveFileX;GetLastError;err;MV 'MV'⎕NA'I kernel32.C32MoveFileEx'A' <0T <0T I4' ⍝ Try for best function :If 0≠MV filenames,3 ⍝ REPLACE_EXISTING (1) + COPY_ALLOWED (2) :Return :EndIf ⎕NA'I4 kernel32.C32|GetLastError' :Select err←GetLastError :Case 120 ⍝ ERROR_CALL_NOT_IMPLIMENTED 'MoveFileX'⎕NA'I Kernel32.C32MoveFile'A' <0T <0T' ⍝ accept 2nd best - win 95 :If 0≠MoveFileX filenames :Return :EndIf err←GetLastError :EndSelect 11 ⎕SIGNAL⍨'MoveFile error:',⍕err ∇ ∇ r←text PutText name;tn ⍝ Write text to file (must be single byte text) :Trap 0 tn←name ⎕NCREATE 0 :Else tn←name ⎕NTIE 0 0 ⎕NRESIZE tn :EndTrap r←text ⎕NAPPEND tn(⎕DR' ') ⎕NUNTIE tn ∇ ∇ RmDir path;GetLastError;RM ⍝ Remove folder using Win32 API 'RM'⎕NA'I kernel32.C32RemoveDirectory'A' <0T' →(0≠RM,⊂path)⍴0 ⎕NA'I4 kernel32.C32|GetLastError' 11 ⎕SIGNAL⍨'RemoveDirectory error:',⍕GetLastError ∇ ∇ SetCurrentDirectory path;SCD;GetLastError ⍝ Set Current Directory using Win32 API 'SCD'⎕NA'I kernel32.C32SetCurrentDirectory'A' <0T' →(0≠SCD,⊂path)⍴0 ⎕NA'I4 kernel32.C32|GetLastError' 11 ⎕SIGNAL⍨'SetCurrentDirectory error:',⍕GetLastError ∇ ∇ rslt←_Filetime_to_TS filetime;⎕IO :If 1≠0⊃rslt←FileTimeToLocalFileTime filetime(⎕IO←0) :OrIf 1≠0⊃rslt←FileTimeToSystemTime(1⊃rslt)0 rslt←0 0 ⍝ if either call failed then zero the time elements :EndIf rslt←1 1 0 1 1 1 1 1/1⊃rslt ⍝ remove day of week ∇ ∇ _FindDefine;WIN32_FIND_DATA WIN32_FIND_DATA←'{I4 {I4 I4} {I4 I4} {I4 I4} {U4 U4} {I4 I4} T[260] T[14]}' 'FindFirstFileX'⎕NA'I4 kernel32.C32|FindFirstFile'A' <0T >',WIN32_FIND_DATA 'FindNextFileX'⎕NA'U4 kernel32.C32|FindNextFile'A' I4 >',WIN32_FIND_DATA ⎕NA'kernel32.C32|FindClose I4' ⎕NA'I4 kernel32.C32|FileTimeToLocalFileTime <{I4 I4} >{I4 I4}' ⎕NA'I4 kernel32.C32|FileTimeToSystemTime <{I4 I4} >{I2 I2 I2 I2 I2 I2 I2 I2}' ⎕NA'I4 kernel32.C32∣GetLastError' ∇ ∇ rslt←_FindFirstFile name;⎕IO rslt←FindFirstFileX name(⎕IO←0) :If ¯1=0⊃rslt ⍝ INVALID_HANDLE_VALUE rslt←0 GetLastError :Else (1 6⊃rslt)_FindTrim←0 ⍝ shorten the file name at the null delimiter (1 7⊃rslt)_FindTrim←0 ⍝ and for the alternate name :EndIf ∇ ∇ rslt←_FindNextFile handle;⎕IO rslt←FindNextFileX handle(⎕IO←0) :If 1≠0⊃rslt rslt←0 GetLastError :Else (1 6⊃rslt)_FindTrim←0 ⍝ shorten the filename (1 7⊃rslt)_FindTrim←0 ⍝ shorten the alternate name :EndIf ∇ ∇ name←name _FindTrim ignored;⎕IO ⍝ Truncates a character vector at the null delimiting byte. ⍝ The null is not included in the result. ⎕IO←0 ⋄ name↑⍨←name⍳0⊃⎕AV ∇ :EndNamespace