1
votes

Elixir 1.3.2

Erlang/OTP 19

Windows 7 (Standard User and Administrator)

I'm trying to hack together a small Elixir script to wrap around commiting files to git. The first thing I do, in order to insure I don't accidentally stage temporary files created by emacs is File.rm("*~"). However, this is what I get:

iex(2)> File.rm("*~")
{:error, :eio}

So I tried File.rm("*.*~"). Same result. I get the same behavior when I run as either a Standard User (which is how I normally work on Windows) or as an administrator so it doesn't seem to be anything with permissions either.

So I captured the files into a list.

iex(15)> {:ok,files} = File.ls
{:ok,
 [".git", ".gitattributes", ".gitignore", "add.factor", "async_ut",
  "async_ut.cs", "cng_maint", "codecvg.cmd", "codecvg_rkt.cmd",
  "codecvg_rkt.cmd~", "CreateBr.vbs", "DevSandbox", "distillery", "dk.cmd",
  "example.scm", "example.sql", "factor", "fsele", "fsharp", "glp.vbs",
  "lwwtww.org", "mrgmain.cmd", "MrgMain.vbs", "mrgtrunk.cmd", "mrgtrunk.cmd~",

(truncated to save space)

I can check for the strings in the list containing ~ and it comes back true. So I'm not imagining the tilde being there.

I created a temporary file called test.txt in the directory. File.rm removed that one just fine so it seems to be something about the ~ which is causing the issue. I also tried these:

iex(7)> File.rm("*\~")
{:error, :eio}
iex(8)> File.rm("*\7F") #7F is hex code of ~
{:error, :eio}

No luck as you can see.

Googling for anything about :eio with Elixir and File.rm didn't turn up anything helpful. I can try installing 1.4.0 to see if that has an effect but I just wanted to see if I was missing something dumb and obvious here.

I've also got cygwin on the machine so I tried removing the files that way. rm *~ worked exactly as expected (under a standard user).

It seems as if this is somehow an Erlang specific issue but I'm aksing here first. Am I doing something obviously wrong?

2
How about Path.wildcard("*~") |> Enum.each(&File.rm/1)? * won't be expanded by File.rm/1.Dogbert
Hmm. Didn't realize that File.rm wouldn't expand the wildcard. Is that documented somewhere and I missed it when I was researching it?Onorio Catenacci
Well, I would consider not documented meaning it won't be expanded.Dogbert
I guess that could be implied, yes. I just assumed that it could handle a wildcard since it seemed to be a wrapper around the OS' rm command.Onorio Catenacci
Unix's rm also does not expand wildcards. I'm not sure about Windows.Dogbert

2 Answers

5
votes

File.rm/1 won't process wildcards automatically as far as I know, you need to use the Path.wildcard/2 function:

File.rm(Path.wildcard("*~"))

or

Path.wildcard('*~') |> Enum.each(fn x -> File.rm(x) end)

for more than one file (which is probably the more general case).

1
votes

On the Unix command line, rm will be called by the shell - and the shell is responsible for wildcard expansion, variable interpolation, etcetera before the actual command is called. So strictly speaking, Unix rm does not support wildcards either - it's the shell that does; rm just loops through its arguments and calls the unlink() system call on each of them. The Erlang library mimics this behaviour.

(On Windows, the shell does not do wildcard expansion, at least not the classic shell - I don't know about PowerShell. Commands have to do this themselves, which is hugely annoying when writing command line utilities. At least, this was the state of the art when I dabbled in Windows ;-))