Skip to content
Advertisement

How to pass an extra option in ls using execv()?

I’m trying to execute this simple command ls -1 *.c using the execv() function.

#include<stdio.h>
#include<fcntl.h>
int main(int argc,char* argv[]){
char *arr[3]={"ls","-1","*.c"};
execv("/bin/ls",arr);
}

The output I’m getting is

ls: cannot access *.c: No such file or directory

Advertisement

Answer

There’s a big problem in your code: execv can’t tell how big the array you’re passing it is. You absolutely need a terminating NULL element to mark the end:

char *arr[] = { "ls", "-1", "*.c", NULL };

OK, now that we have a valid execv invocation, we can deal with the ls error.

Calling execv like this is equivalent to running

'ls' '-1' '*.c'

on the command line (which would produce the same error).

When you do

ls -1 *.c

on the command line, ls never sees *.c because the shell expands wildcards and passes a list of matching filenames to ls.

If you want to replicate that in your C code, you have to do the same thing manually. See e.g. man glob for a function that does most of the work. Here’s an adapted example from the man page that shows the general principle:

glob_t globbuf;

globbuf.gl_offs = 2;
glob("*.c", GLOB_DOOFFS, NULL, &globbuf);
globbuf.gl_pathv[0] = "ls";
globbuf.gl_pathv[1] = "-1";
execv("/bin/ls", globbuf.gl_pathv);
User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement