erlang is a strange language to me, this week i've been playing with multiple languages and I've come here for help often, now I'm on erlang and I'm stuck once again :)
Basically All i'm trying to do is the following but in erlang:
Dim objFSO, objFile, objFolder
Set objFSO = Server.CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder(currentDirectory))
For Each objFile in objFolder.Files
do something with the file
do something else
do more stuff
Next
The closest i've come is:
-export([main/1]).
main([]) ->
find:files("c:\","*.txt", fun(F) -> {
File, c:c(File)
}end).
clearly, not working and nothing like how i'd need it to be.. but I have tried many ways and read many example but simply cant figure out a solution maybe the language just isnt ment for this kind of stuff?
And this is needed as a escript (erlang script)
This fits here: How do I loop through only directories in bash? Solid array under bash, (accepting spaced dirnames): dirs=(/tmp/*/);dirs=("${dirs[@]%/}");dirs=("${dirs[@]#/tmp/}") , then printf "%s\n" "${dirs[@]}" or for dir in "${dirs[@]}" ;do ...
It's tough to recommend exactly which method you should use because your "do something" pseudocode is too vague.
There are two main ways one iterates over a list of something in a functional language like Erlang: map
and fold
.
The big question comes down to this: What do you want to do with the files? Do you want to total something up for the files (ie, total file size or something), or do you want to store some value for each file (ie each file size individually) or do you want to do something to the files and you don't care what the return values for those files are (ie renaming each file)?
I'll give an example of each quickly here using a list of files returned from file:list_dir/1
:
{ok, Filenames} = file:list_dir("some_directory"),
Folding
Here we'll total the filesizes of all files in the directory using lists:foldl
(as @legoscia mentioned, in this case, filelib:fold_files
is probably the better choice)
TotalSize = lists:foldl(fun(Filename,SizeAcc) ->
FileInfo = file:read_file_info("some_directory/" ++ Filename),
FileSize = FileInfo#file_info.size,
SizeAcc + FileSize
end, 0, Filenames).
Mapping
Here, we'll get a list of filenames along with the filesize for each individual file using lists:map
. The resultant list will be of the format = [{"somefile.txt",452}, {"anotherfile.exe",564},...]
:
FileSizes = lists:map(fun(Filename) ->
FileInfo = file:read_file_info("some_directory/" ++ Filename),
FileSize = FileInfo#file_info.size,
{Filename,FileSize}
end,Filenames).
Foreach (a variant of mapping)
The alternative of just renaming files but not caring about recording any data about the files is to demonstrate the use of lists:foreach
, which is generally used exclusively for side-effect programming in which you don't care about the return values, and it works like lists:map
, but doesn't return anything useful (it just returns the atom ok
):
In this case, I'll show renaming each file by adding a ".old" extension to each filename:
lists:foreach(fun(Filename) ->
OldFile = "some_directory/" ++ Filename,
NewFile = OldFile ++ ".old",
file:rename(OldFile, NewFile),
end,Filenames).
Recursion
Of course, the raw version of all of these - if map
, fold
, foreach
, or list comprehensions (which I didn't cover, but are basically another variant of map
with a filter
component) are too restricting for whatever reason - you can do things recursively:
do_something_with_files([]) -> ok;
do_something_with_files([CurrentFile|RestOfFiles]) ->
do_something(CurrentFile),
do_something_with_files(RestOfFiles).
There are a lot of ways to do what you need with Erlang, but unlike with procedural languages like VB, you must think a little ahead to what you want to track or do in order to determine how you wish to iterate over your lists, since you're limited by immutable variables in Erlang.
Note: In order to use the #file_info
record, you'll need to include the file.hrl file at the top of your module with:
-include_lib("kernel/include/file.hrl").
i wrote a file system indexer recently and here below, i provide you with a module, which can traverse a directory (s) and lets you so what ever you want with the files it finds or the folders it finds. What it does is that it will spawn
a new process to handle any inner directory. You will provide two Functional Objects
, one that will deal with directories and the other will deal with the files.
%% @doc This module provides the low level APIs for reading, writing, %% searching, joining and moving within directories. %% @end
-module(file_scavenger_utilities). %%% ------- EXPORTS ------------------------------------------------------------------------------- -compile(export_all). %%% ------- INCLUDES ----------------------------------------------------------------------------- %%% -------- MACROS ------------------------------------------------------------------------------ -define(IS_FOLDER(X),filelib:is_dir(X)). -define(IS_FILE(X),filelib:is_file(X)). -define(FAILED_TO_LIST_DIR(X), error_logger:error_report(["* File Scavenger Utilities Error * ", {error,"Failed to List Directory"},{directory,X}])). -define(NOT_DIR(X), error_logger:error_report(["* File Scavenger Utilities Error * ", {error,"Not a Directory"},{alleged,X}])). -define(NOT_FILE(X), error_logger:error_report(["* File Scavenger Utilities Error * ", {error,"Not a File"},{alleged,X}])). %%%--------- TYPES -------------------------------------------------------------------------------
%% @type dir() = string(). %% Must be containing forward slashes, not back slashes. Must not end with a slash %% after the exact directory.e.g this is wrong: "C:/Program Files/SomeDirectory/" %% but this is right: "C:/Program Files/SomeDirectory" %% @type file_path() = string(). %% Must be containing forward slashes, not back slashes. %% Should include the file extension as well e.g "C:/Program Files/SomeFile.pdf" %% -----------------------------------------------------------------------------------------------
%% @doc Enters a directory and executes the fun ForEachFileFound/2 for each file it finds %% If it finds a directory, it executes the fun %% ForEachDirFound/2. %% Both funs above take the parent Dir as the first Argument. Then, it will spawn an %% erlang process that will spread the found Directory too in the same way as the parent directory %% was spread. The process of spreading goes on and on until every File (wether its in a nested %% Directory) is registered by its full path. %% @end %% %% @spec new_user(dir(),funtion(),function())-> ok.spread_directory(Dir,Top_Directory,ForEachFileFound,ForEachDirFound) when is_function(ForEachFileFound),is_function(ForEachDirFound) -> case ?IS_FOLDER(Dir) of false -> ?NOT_DIR(Dir); true -> F = fun(X)-> FileOrDir = filename:absname_join(Dir,X), case ?IS_FOLDER(FileOrDir) of true -> (catch ForEachDirFound(Top_Directory,FileOrDir)), spawn(fun() -> ?MODULE:spread_directory(FileOrDir,Top_Directory,ForEachFileFound,ForEachDirFound) end); false -> case ?IS_FILE(FileOrDir) of false -> {error,not_a_file,FileOrDir}; true -> (catch ForEachFileFound(Top_Directory,FileOrDir)) end end end, case file:list_dir(Dir) of
{error,_} -> ?FAILED_TO_LIST_DIR(Dir); {ok,List} -> lists:foreach(F,List) end end.
To test it, below is usage:
E:\Applications>erl Eshell V5.9 (abort with ^G) 1> Dir = "E:/Ruth". "E:/Ruth" 2> TopDir = "E:/Ruth". "E:/Ruth" 3> Folder = fun(Parent,F) -> io:format("\n\t~p contains Folder: ~p~n",[Parent,F]) end. #Fun<erl_eval.12.111823515> 4> File = fun(Parent,F) -> io:format("\n\t~p contains File: ~p~n",[Parent,F]) end. #Fun<erl_eval.12.111823515> 5> file_scavenger_utilities:spread_directory(Dir,TopDir,File,Folder)."E:/Ruth" contains File: "e:/Ruth/Thumbs.db" "E:/Ruth" contains File: "e:/Ruth/Robert Passport.pdf" "E:/Ruth" contains File: "e:/Ruth/new mixtape.mp3" "E:/Ruth" contains File: "e:/Ruth/Manning - Java 3d Programming.pdf" "E:/Ruth" contains File: "e:/Ruth/jcrea350.zip" "E:/Ruth" contains Folder: "e:/Ruth/java-e books" "E:/Ruth" contains File: "e:/Ruth/Java Programming Unleashed.pdf" "E:/Ruth" contains File: "e:/Ruth/Java Programming Language Basics.pdf" "E:/Ruth" contains File: "e:/Ruth/java-e books/vb blackbook.pdf.pdf"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With