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:
os_obj(Obj,Type,Depth)
termsThe 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 ).
date(Y,M,D)
term).os_sub( Dir, SubDirs, [return(dirs)] )
.os_sub( Dir, Files, [return(files)] )
.os_sub( Dir, Objs, [] )
.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.)
as_term(AsTerm)
Whether to return objects as terms, eg. a/b rather than atomic 'a/b'. (false,true)blocked_dirs(Bdirs)
A single or a list of sub dirs we want to avoid. Every matching directory will be ignored. ([])blocked_files(Bfiles)
A single or list of files to avoid (all matching-by-name files will be avoided). ([])depth(Depth)
Depth to descent to. Negative means all the way to the leaves. (-1/integer)downcase(Dcase)
downcase all os objects? (false,true,ms_wins)
Idealy on MS-wins we want false
as default but as we switched to SWI's
predicate_options/3, this needs conditional compilations which
we try to avoid
leading_dot_dir(Lead)
Whether to include leading './' . (false,true)partial(Partial)
Whether to include partial paths and in what order.
Setting partial to false
can be used to only get objects at excactly depth Depth.
(pre,post,false).
reply(RetType)
object
returns only the os object, while os_term
returns os_obj(Obj,Otype,Depth)
.return(RetType)
What shall be returned ?files
anddirs
return only files and dirs respectively.mixed
for inlining files and dirs. andseparate
returnsos(Dirs,Files,..)
. (mixed,dirs,files,separate).
warn(Warning)
Print an informational message if reading directory contents fails. (true,false)
os_print( +Objects, [] )
.Opts is a single term or list of the following terms:
root(Root)
parent directory, relative to which to decorate ('.')deco(Deco)
decorates verified directories with a trailing slash (false,dir,remove).
When Objects is a list of os/3 terms, the default is dir
, as it is for free.
In this case it can be surpressed by remove
.os_obj_strip(OOStrip)
strip os_obj/3 structures off (only print name when true
(default)return(Return)
as in os_sub/3. The idea is os_print/2 can section the output appropriately. (See also so_sub_print/3.)
as in os_sub/3.
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' ).
-
.
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 ).