os_sub: Collect files and sub-directories.

This is a versatile library for looking into the contents of file systems. The main scenario is that of finding all the directories and files within a single directory. There is a large number of options that can control its behaviour.

Installation and usage:

   ?- pack_install( os_sub ).
   
   ?- [library(os_sub)].

Highlights:

The pack has been developed under linux but should also work on other OSes.

When it comes to root directories, the minus symbol (-) is alias for '.' (os_dot_alias/1). This is to avoid typing the awkward long form.

To see the limited number of debug statement print at each sub-directory use:

   debug( os_sub ).

Introductory examples:

?-   absolute_file_name( pack(os_sub), OsSub ), working_directory(_, OsSub ).
?-   ls( '..' ).

                        Downloads/   os_sub/      real/        spuds/


?- os_sub_dirs( '.', Dirs ), os_print( Dirs ), arg( 1, Dirs, List ), length( List, LenD ).
doc
prolog

Dirs = os([doc, prolog]),
List = [doc, prolog],
LenD = 2.

?- os_sub_files( '.', Files ), os_print( Files ), os_length( Files, LenF ).

 doc/changes.txt
pack.pl
 prolog/os_sub.pl

OsFiles = os(['doc/changes.txt', 'pack.pl', 'prolog/os_sub.pl']),
List = ['doc/changes.txt', 'pack.pl', 'prolog/os_sub.pl'],
LenF = 3.


?- os_sub( -, Both ), os_print( Both ), os_length( Both, LenB ).

...
LenB = 5.


?-  os_sub( -, Both ), os_print( Both, deco(dir) ).

doc/
 doc/changes.txt
pack.pl
prolog/
 prolog/os_sub.pl

Both = os([doc, 'doc/changes.txt', 'pack.pl', prolog, 'prolog/os_sub.pl']).


?- os_sub( '.', Both, reply(os_term) ), os_print( Both, [] ).

% output as above, for os_term reply directories are decorated by default.

Tests error in deco/1 option:

?- os_sub( '.', Both ), os_print( Both, deco(root) ).
ERROR: Error for option: deco of predicate: os_print/2.
ERROR: Type error: `oneof([false,dir,remove])' expected, found `root'

Use a depth limit:

?- Opts = [return(mixed),depth(1)],
   os_sub( '..', Objs, Opts ), os_print( Objs ).

Only get objects at depth 3:

  Opts = [return(mixed),partial(false),depth(3)],
  os_sub('../..', os(Objs), Opts), os_print( Objs ).

Get Dirs and Files in one pass but in separate lists:

?- os_sub( '.', Objs, [return(separate)] ),
   Objs = os(Dirs,Files),
   write(files:here ), nl, os_print( Files  ),
   write( dirs:here ), nl, os_print( Dirs ).

Scan over 1 million entries:

?- statistics, os_sub( '/', Objs, blocked_dirs([home,media,mnt,proc,sys]) ),
   write( '---' ), nl, statistics, os_length(Objs,Lens), write(Lens), nl.

  ...   % run on a dual cpu 2.6 M370 Inter 4GB mem laptop  with Bodhi linux 2.2.0
  341.306 seconds cpu time for 23,962,947 inferences
  ----

1140092        (Objects)

Although subsequent identical calls take quite a bit longer !

To turn diagnostics about unreadable dirs, off:

?- os_sub( '/', Objs, [blocked_dirs([home,media,mnt,proc,sys]),warn(false)] ).

Get Swi's installed library structure.

?- file_search_path(swi, Swi), os_sub_files(Swi, SwiFs),
   os_length(SwiFs , LenFs), write(LenFs), nl.

?- absolute_file_name(swi(library),Abs), os_sub(Abs,All),
   os_print(All,[root(Abs),deco(dir)] ).

?- absolute_file_name(swi(library),Abs), os_sub(Abs,All,depth(0)),
   os_print(All,[root(Abs),deco(dir)] ),
   os_length(All, Lens ).

Use of downcase/2 option.

?- Opts = [depth(0),downcase(true)],
   absolute_file_name(swi(library),Abs), os_sub(Abs,All,Opts),
   os_print(All,[root(Abs),deco(dir)] ).

Test os_sub_print/3.

?- absolute_file_name(swi(library),Abs),
   Opts = [return(separate),file_links(separate)],
   os_sub_print( -, Reply, Opts ).
author
- Nicos Angelopoulos
version
- 0:0:6, 2013/03/19
See also
- http://stoics.org.uk/~nicos/sware/os_sub
- http://www.swi-prolog.org/pack/list?p=os_sub
license
- Perl Artistic
To be done
- decorate symlinks in os_print/2
- term replies should have sym files as a separate Type
- directory sym links ?
- test on ms_wins and mac_os
os_sub_version (-Version, -Date)
Version and release Date (date(Y,M,D) term).
os_sub_dirs (+Dir, -SubDirs)
SubDirs are all reachable subdirectories of Dir. Short for os_sub( Dir, SubDirs, [return(dirs)] ).
os_sub_files (+Dir, -Files)
Files are all non-directories appearing in Dir. Short for os_sub( Dir, Files, [return(files)] ).
os_sub (+Dir, -Objs)
Short for os_sub( Dir, Objs, [] ).
os_sub (+Dir, -Objs, +Opts)
Return the OS objects (Objs) from within Dir as controlled by Opts. The predicate performs a depth first, nested search. It uses difference lists to be slightly more efficient, however the overall design goal is that of flexibility not efficiency. All returned objects (Objs) are shown relatively to Dir.

The minus symbol (-) is alias for '.' when it comes to root directories in this pack. This is to avoid typing the awkard long form.

Opts should be a single or list of terms of the following options. (First values are the defaults.)

os_print (+Objs)
Print each element in Objs. This can be a list or the output argument from os_sub/3. Short for os_print( +Objects, [] ).
os_print (+Objs, +Opts)
Print each element in the list of Objs, by pre-tabbing it with as many tabs as subdirs there are in the respective element.

Opts is a single term or list of the following terms:

os_sub_print (+Dir, -Reply, +Opts)
Combines os_sub/3 and os_print/2. Opts takes the comination of the options for these two predicates. The idea is that os_print/2 gets the correct options for printing the os/n components.
os_length (+OsReply, -ListOfLengths)
Maplist length/2 to the arguments of OsReply.
os_atom_term (?DirAtom, ?DirTerm)
os_atom_term( +DirAtom, -DirTerm )

os_atom_term( -DirAtom, +DirTerm )

os_atom_term( +DirAtom, +DirTerm )

Convert between atom and term representations of directories and files.
     os_atom_term( './abc/edf.g', '.'/abc/'edf.g' ).
os_to_atom (+Either, -Atom)
Either's atomic representation is Atom. Dir may be an atom or term representing an OS path.
os_dot_alias (-Alias)
Shows library defined aliases for '.'. Currently there is a single alias -. Users can define their own aliases by means of (user:)os_user_dot_alias/1 clauses.
  os_sub_files(-, SbuFs ).
  assert( os_user_dot_alias(+) ).
  file_search_path(swi, Swi), cd( Swi ), os_sub_dirs( +, SwiSdirs ), length( SwiSdirs, Len ).