3

How can I expand wildcard commandline arguments in Julia?

The shell doesn't seem to expand them before they get there.

If I call my script as julia script.jl *.dat, my output is just *.dat

for arg in ARGS
    println(arg)
end

If I write the equivalent program in Java:

public class rejig {
    public static void main(String[] args) throws Exception {
        for(int i = 0; i < args.length; i++) {
            System.out.println(args[i]);
        }
    }
}

and call it as java rejig *.dat, I get a listing of all the DAT files in the current directory.

My searching along the lines of "command line", "wildcards", and the like hasn't got me very far.

How do I get Julia to give the same output as the Java code?

Gnimuc
  • 8,098
  • 2
  • 36
  • 50
masher
  • 3,814
  • 4
  • 31
  • 35
  • Is this on Windows? On a unix-like system, this should work consistently because the shell expands unquoted arguments before calling the command. Java tries to emulate shell wildcard behavior on Windows, see: http://stackoverflow.com/questions/25948706/java-command-line-arguments-stop-expanding-wildcard-symbols However, Julia currently does not. – Isaiah Norton Oct 20 '15 at 13:26
  • It is on Windows. Bugger. I knew it was the shell expanding the wildcards, but I didn't realise that DOS didn't do that. – masher Oct 21 '15 at 00:11

2 Answers2

4

I wrote a pure-Julia implementation of Glob (aka fnmatch or wildcard commandline expansion) at https://github.com/vtjnash/Glob.jl, which also available via Pkg.add("Glob").

This can be used for platform-independent wildcard expansion, such as your *.dat example.

user1712368
  • 400
  • 3
  • 7
  • This is what I started to write, then gave up as being too much work for what I wanted to do. I'll check it out. – masher Oct 23 '15 at 00:05
2

As explained in the comment, the shell is the program which expands the wildcards. This expansion is called glob expansion and there are functions in the standard C library which do it (and the shell probably uses itself).

Practically, here is an example of interfacing with the standard libc to expand wildcards:

type GlobType
    pathc::Int64
    names::Ptr{Ptr{UInt8}}
    slots::Int64
    extra1::Int64
    extra2::Int64
end

function parseglob(gb::GlobType)
    i=1
    res = UTF8String[]
    while i<=gb.pathc
        p = unsafe_load(gb.names,i)
        if p==C_NULL return res ; end
        push!(res,bytestring(p))
        i+=1
    end
    res
end

function glob(filepattern::AbstractString)
    gb = GlobType(0,C_NULL,0,0,0)
    retval = ccall((:glob,"libc"),Cint,
                   (Ptr{UInt8},Cint,Ptr{Void},Ptr{GlobType}),
                   filepattern,0,C_NULL,&gb)
    res = ( retval==0 ? parseglob(gb) : UTF8String[] )
    ccall((:globfree,"libc"),Void,(Ptr{GlobType},),&gb)
    res
end

# glob("*.jl") # ["glob.jl"] on my machine

the library routine has many flags and options which might be of interest to you.

Dan Getz
  • 17,002
  • 2
  • 23
  • 41