Charles Okwuagwu
Charles Okwuagwu

Reputation: 10876

How do you get directory listing sorted by date in Elixir?

How do you get directory listing sorted by date in Elixir?

File.ls/1 gives list sorted by filename only.

No other functions in File module seem relevant for this.

Upvotes: 1

Views: 1108

Answers (2)

Adam Millerchip
Adam Millerchip

Reputation: 23129

Maybe there's a built-in function I don't know about, but you can make your own by using File.stat!/2:

File.ls!("path/to/dir")
|> Enum.map(&{&1, File.stat!(Path.join("path/to/dir", &1)).ctime})
|> Enum.sort(fn {_, time1}, {_, time2} -> time1 <= time2 end)

Example output:

[
  {"test", {{2019, 3, 9}, {23, 55, 48}}},
  {"config", {{2019, 3, 9}, {23, 55, 48}}},
  {"README.md", {{2019, 3, 9}, {23, 55, 48}}},
  {"_build", {{2019, 3, 9}, {23, 59, 48}}},
  {"test.xml", {{2019, 3, 23}, {22, 1, 28}}},
  {"foo.ex", {{2019, 4, 20}, {4, 26, 5}}},
  {"foo", {{2019, 4, 21}, {3, 59, 29}}},
  {"mix.exs", {{2019, 7, 27}, {8, 45, 0}}},
  {"mix.lock", {{2019, 7, 27}, {8, 45, 7}}},
  {"deps", {{2019, 7, 27}, {8, 45, 7}}},
  {"lib", {{2019, 7, 27}, {9, 5, 36}}}
]

Upvotes: 3

sbacarob
sbacarob

Reputation: 2212

Edit: As pointed out in a comment, this assumes you're in the directory you want to see the output for. If this is not the case, you can specify it by adding the :cd option, like so:

System.cmd("ls", ["-lt"], cd: "path/to/dir")

You can also make use of System.cmd/3 to achieve this.

Particularly you want to use the "ls" command with the flag "-t" which will sort by modification date and maybe "-l" which will provide extra information.

Therefore you can use it like this:

# To simply get the filenames sorted by modification date

System.cmd("ls", ["-t"])

# Or with extra info

System.cmd("ls", ["-lt"])

This will return a tuple containing a String with the results and a number with the exit status.

So, if you just call it like that, it will produce something like:

iex> System.cmd("ls", ["-t"])
{"test_file2.txt\ntest_file1.txt\n", 0}

Having this, you can do lots of things, even pattern match over the exit code to process the output accordingly:

case System.cmd("ls", ["-t"]) do
  {contents, 0} ->
    # You can for instance retrieve a list with the filenames
    String.split(contents, "\n")
  {_contents, exit_code} ->
    # Or provide an error message
    {:error, "Directory contents could not be read. Exit code: #{exit_code}"
end

If you don't want to handle the exit code and just care about the contents you can simply run:

System.cmd("ls", ["-t"]) |> elem(0) |> String.split("\n")

Notice that this will however include an empty string at the end, because the output string ends with a newline "\n".

Upvotes: 2

Related Questions