|
Home > Archive > Unix Programming > November 2005 > How to pass arguments with '*' to execvp()?
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
How to pass arguments with '*' to execvp()?
|
|
| Alex Vinokur 2005-11-26, 2:50 am |
| I tried to execute the following command line:
strcpy (cmd, "ls");
strcpy (args[0], "ls");
strcpy (args[1], "-l");
strcpy (args[2], "*.c");
args[3] = NULL;
execvp (cmd, args);
However I have got an error message:
----------------------------
ls: '*.c': No such file or directory
----------------------------
How to pass arguments with '*' to execvp()?
Thanks,
--
Alex Vinokur
email: alex DOT vinokur AT gmail DOT com
http://mathforum.org/library/view/10978.html
http://sourceforge.net/users/alexvn
| |
| Nils O. Selåsdal 2005-11-26, 2:50 am |
| Alex Vinokur wrote:
> I tried to execute the following command line:
>
> strcpy (cmd, "ls");
> strcpy (args[0], "ls");
> strcpy (args[1], "-l");
> strcpy (args[2], "*.c");
> args[3] = NULL;
>
> execvp (cmd, args);
>
> However I have got an error message:
> ----------------------------
> ls: '*.c': No such file or directory
> ----------------------------
>
>
> How to pass arguments with '*' to execvp()?
The shell is responsible for expanding pathnames
containing * . So run a shell that runs ls -l *.c
as in e.g. sh -c ls -l *.c
| |
| Pascal Bourguignon 2005-11-26, 2:50 am |
| "Alex Vinokur" <alexvn@users.sourceforge.net> writes:
> I tried to execute the following command line:
>
> strcpy (cmd, "ls");
> strcpy (args[0], "ls");
> strcpy (args[1], "-l");
> strcpy (args[2], "*.c");
> args[3] = NULL;
>
> execvp (cmd, args);
>
> However I have got an error message:
> ----------------------------
> ls: '*.c': No such file or directory
> ----------------------------
>
>
> How to pass arguments with '*' to execvp()?
Using opendir, readdir and fnmatch.
You can also have a look at the sources of bash.
--
__Pascal Bourguignon__ http://www.informatimago.com/
| |
| Alex Vinokur 2005-11-26, 7:49 am |
|
"Pascal Bourguignon" <spam@mouse-potato.com> wrote in message news:87fypjvm8u.fsf@thalassa.informatimago.com...
> "Alex Vinokur" <alexvn@users.sourceforge.net> writes:
>
>
> Using opendir, readdir and fnmatch.
[snip]
OK.
I found sample at http://docs.hp.com/en/B2355-90694/fnmatch.3C.html
-----------------------
pattern = "*.c";
while(dp = readdir(dirp)){
if((fnmatch(pattern, dp->d_name,0)) == 0){
/* do processing for match */
...
}
}
-----------------------
But how to apply that to passing args to execvp (cmd, args) ?
--
Alex Vinokur
email: alex DOT vinokur AT gmail DOT com
http://mathforum.org/library/view/10978.html
http://sourceforge.net/users/alexvn
| |
| Pascal Bourguignon 2005-11-26, 7:49 am |
| "Alex Vinokur" <alexvn@x-privat.org> writes:
> [snip]
>
> OK.
> I found sample at http://docs.hp.com/en/B2355-90694/fnmatch.3C.html
>
> -----------------------
> pattern = "*.c";
>
> while(dp = readdir(dirp)){
> if((fnmatch(pattern, dp->d_name,0)) == 0){
> /* do processing for match */
> ...
> }
> }
> -----------------------
>
> But how to apply that to passing args to execvp (cmd, args) ?
You implement the "do processing for match" part.
--
__Pascal Bourguignon__ http://www.informatimago.com/
There is no worse tyranny than to force a man to pay for what he does not
want merely because you think it would be good for him. -- Robert Heinlein
| |
| Alex Vinokur 2005-11-26, 5:50 pm |
|
"Pascal Bourguignon" <spam@mouse-potato.com> wrote in message news:87br07ven4.fsf@thalassa.informatimago.com...
> "Alex Vinokur" <alexvn@x-privat.org> writes:
>
> You implement the "do processing for match" part.
[snip]
Something like?
---------------------------
strcpy (cmd, "ls");
strcpy (args[0], "ls");
strcpy (args[1], "-l");
// strcpy (args[2], "*.c");
args[3] = NULL;
pattern = "*.c";
while(dp = readdir(dirp))
{
if((fnmatch(pattern, dp->d_name,0)) == 0)
{
strcpy (args[2], )dp->d_name);
// stuff withh forks
execvp (cmd, args);
// stuff
}
}
---------------------------
But in this case there will be several process created by execvp().
Of course, we need the only process created by execvp().
--
Alex Vinokur
email: alex DOT vinokur AT gmail DOT com
http://mathforum.org/library/view/10978.html
http://sourceforge.net/users/alexvn
| |
| Pascal Bourguignon 2005-11-26, 5:50 pm |
| "Alex Vinokur" <alexvn@x-privat.org> writes:
> [snip]
>
> Something like?
>
> ---------------------------
> strcpy (cmd, "ls");
> strcpy (args[0], "ls");
> strcpy (args[1], "-l");
> // strcpy (args[2], "*.c");
> args[3] = NULL;
>
> pattern = "*.c";
> while(dp = readdir(dirp))
> {
> if((fnmatch(pattern, dp->d_name,0)) == 0)
> {
>
> strcpy (args[2], )dp->d_name);
> // stuff withh forks
> execvp (cmd, args);
> // stuff
>
> }
> }
> ---------------------------
>
> But in this case there will be several process created by execvp().
> Of course, we need the only process created by execvp().
Then if you need to call execvp only once, why do you call it inside the loop?
What you want to do is:
1- collect the file names matching *.c into a list.
2- build the list of arguments as "ls", "-1" followed by the list
collected by step 1.
3- call execvp with cmd and the list built by step 2.
--
__Pascal Bourguignon__ http://www.informatimago.com/
This is a signature virus. Add me to your signature and help me to live
| |
| Giorgos Keramidas 2005-11-27, 2:50 am |
| "Alex Vinokur" <alexvn@x-privat.org> writes:
> "Pascal Bourguignon" <spam@mouse-potato.com> wrote in message
>news:87fypjvm8u.fsf@thalassa.informatimago.com... >"Alex
>Vinokur" <alexvn@users.sourceforge.net> writes: >> >> I tried to
>execute the following command line: >> >> strcpy (cmd, "ls"); >>
>strcpy (args[0], "ls"); >> strcpy (args[1], "-l"); >> strcpy
>(args[2], "*.c"); >> args[3] = NULL; >> >> execvp (cmd, args);
>---------------------------- >> ls: '*.c': No such file or
>directory >> ---------------------------- >> >> How to pass
>arguments with '*' to execvp()? > > Using opendir, readdir and
>fnmatch. [snip] OK. I found sample at
>http://docs.hp.com/en/B2355-90694/fnmatch.3C.html
>----------------------- pattern = "*.c"; while(dp =
>readdir(dirp)){ if((fnmatch(pattern, dp->d_name,0)) == 0){ /* do
>processing for match */ ... } } ----------------------- But how
>to apply that to passing args to execvp (cmd, args) ?
By building a new argv[] array for the command you're executing, and
copying the necessary command-line arguments in there, i.e. with
something like:
#define ARGV_GROWSIZE 10
char **tmp_argv;
char **new_argv = NULL;
int new_argvsize = 0;
int new_argc = 0, k;
while ((dp = readdir(dirp)) != NULL) {
if (fnmatch(pattern, dp->d_name, 0) != 0)
continue;
if (new_argc >= new_argvsize) {
/* Grow new_argv[] a bit. */
tmp_argv = realloc((new_argvsize + ARGV_GROWSIZE) *
sizeof(*new_argv));
if (tmp_argv == NULL)
goto err;
new_argv = tmp_argv;
new_argvsize += ARGV_GROWSIZE;
}
new_argv[new_argc] = strdup(dp->d_name);
if (new_argv[new_argc] == NULL)
goto err;
new_argc++;
}
...
err:
for (k = 0; k < new_argc; k++) {
free(new_argv[k]);
new_argv[k] = NULL;
}
new_argc = 0;
free(new_argv);
new_argv = NULL;
new_argvsize = 0;
return ENOMEM;
Then you can pass the new_argv[] to execvp(), as usual.
| |
| Giorgos Keramidas 2005-11-27, 2:50 am |
| Giorgos Keramidas <keramida@ceid.upatras.gr> writes:
> "Alex Vinokur" <alexvn@x-privat.org> writes:
[snip messed up quotation]
[vbcol=seagreen]
> By building a new argv[] array [...]
Whoops! Somehow I or cvs-emacs/Gnus managed to mangle the original post
text in horrible ways. I apologize for that.
| |
| Alex Vinokur 2005-11-27, 5:53 pm |
|
"Pascal Bourguignon" <spam@mouse-potato.com> wrote in message news:87zmnrt6rg.fsf@thalassa.informatimago.com...
[snip]
> What you want to do is:
>
> 1- collect the file names matching *.c into a list.
>
> 2- build the list of arguments as "ls", "-1" followed by the list
> collected by step 1.
>
> 3- call execvp with cmd and the list built by step 2.
[snip]
OK.
But what to do with the following command line:
find . -name "*.c" -print
?
--
Alex Vinokur
email: alex DOT vinokur AT gmail DOT com
http://mathforum.org/library/view/10978.html
http://sourceforge.net/users/alexvn
| |
| Pascal Bourguignon 2005-11-27, 5:53 pm |
| "Alex Vinokur" <alexvn@x-privat.org> writes:
> "Pascal Bourguignon" <spam@mouse-potato.com> wrote in message news:87zmnrt6rg.fsf@thalassa.informatimago.com...
> [snip]
> [snip]
>
> OK.
>
> But what to do with the following command line:
> find . -name "*.c" -print
> ?
Yes, what?
--
__Pascal Bourguignon__ http://www.informatimago.com/
Nobody can fix the economy. Nobody can be trusted with their finger
on the button. Nobody's perfect. VOTE FOR NOBODY.
| |
| Måns Rullgård 2005-11-27, 5:53 pm |
| "Alex Vinokur" <alexvn@x-privat.org> writes:
> "Pascal Bourguignon" <spam@mouse-potato.com> wrote in message news:87zmnrt6rg.fsf@thalassa.informatimago.com...
> [snip]
> [snip]
>
> OK.
>
> But what to do with the following command line:
> find . -name "*.c" -print
The same thing as the shell does: remove the quotes. You might want
to look at the wordexp(3) function.
--
Måns Rullgård
mru@inprovide.com
| |
| Bjorn Reese 2005-11-28, 6:04 pm |
| Alex Vinokur wrote:
> But what to do with the following command line:
> find . -name "*.c" -print
Nils already provided you with the proper solution. Expressed in
code, it is something like this (disclaimer: untested code)
strcpy(command, "find . -name \"*.c\" -print");
execl("/bin/sh", "/bin/sh", "-c", command, NULL);
--
mail1dotstofanetdotdk
| |
| Mr. Uh Clem 2005-11-29, 2:50 am |
| Bjorn Reese wrote:
> Alex Vinokur wrote:
>
>
>
> Nils already provided you with the proper solution. Expressed in
> code, it is something like this (disclaimer: untested code)
>
> strcpy(command, "find . -name \"*.c\" -print");
> execl("/bin/sh", "/bin/sh", "-c", command, NULL);
>
Why use the shell here?? How about (same disclaimer):
execl("/usr/bin/find", "/usr/bin/find", ".", "-name", "*.c", "-print",
(char *)0);
Unlike doing an "ls *.c" shell command, the find command itself
handles the * wildcard.
--
Clem
"If you push something hard enough, it will fall over."
- Fudd's first law of opposition
| |
| David Schwartz 2005-11-29, 2:50 am |
|
"Alex Vinokur" <alexvn@users.sourceforge.net> wrote in message
news:1132990989.724364.16910@o13g2000cwo.googlegroups.com...
>I tried to execute the following command line:
> strcpy (cmd, "ls");
> strcpy (args[0], "ls");
> strcpy (args[1], "-l");
> strcpy (args[2], "*.c");
> args[3] = NULL;
>
> execvp (cmd, args);
>
> However I have got an error message:
> ----------------------------
> ls: '*.c': No such file or directory
> ----------------------------
> How to pass arguments with '*' to execvp()?
Exactly as you did it. The 'ls' command properly told you that there is
no file called '*.c'.
The 'ls' command has no ability to expand wildcards. There is nothing
special about the '*' character to 'exec' functions, and you don't have to
do anything special to pass '*'s.
DS
| |
| Bjorn Reese 2005-11-29, 5:58 pm |
| Mr. Uh Clem wrote:
> Why use the shell here?? How about (same disclaimer):
Because the original poster keeps asking about how to execute
different commands as if they were executed from a shell. Using
the shell solves his problems once and for all.
--
mail1dotstofanetdotdk
| |
| Anthony de Almeida Lopes 2005-11-30, 2:50 am |
| On Sun, 27 Nov 2005 17:01:39 +0000, Måns Rullgård wrote:
[snip]
>
> The same thing as the shell does: remove the quotes. You might want
> to look at the wordexp(3) function.
Definitely. I was surprised nobody mentioned that before. Also check out
'man 3 glob' and 'man 7 glob' for yet more information. Very cool stuff 
- Anthony
| |
| Mr. Uh Clem 2005-11-30, 5:55 pm |
| Bjorn Reese wrote:
> Mr. Uh Clem wrote:
>
>
>
> Because the original poster keeps asking about how to execute
> different commands as if they were executed from a shell. Using
> the shell solves his problems once and for all.
>
Very true, but he also asked specifically about running find and
find does not need any help from the shell because find does
its own filename matching. So I felt it should be pointed out
that such programs can be directly exec*'d.
It's also worth pointing out that a shell ls command will choke
if there are too many files in the directory. find will survive
this.
Cheers!
--
Clem
"If you push something hard enough, it will fall over."
- Fudd's first law of opposition
| |
| Pascal Bourguignon 2005-11-30, 5:55 pm |
| "Mr. Uh Clem" <uhclem@DutchElmSt.invalid> writes:
> It's also worth pointing out that a shell ls command will choke
> if there are too many files in the directory. find will survive
> this.
You should decide, is it a shell built-in? or is it the ls command?
AFAIK, ls has no other limit on the number of file in a directory than
the virtual memory size. On a 32-bit system, if you can fill between
2GB and 4GB in a directory, ls will happilly load it in memory,
quicksort them, and print them.
On the other hand, shells have been known to have much smaller limits
on the number, or on the size of the wildcard expansions.
--
__Pascal Bourguignon__ http://www.informatimago.com/
Our enemies are innovative and resourceful, and so are we. They never
stop thinking about new ways to harm our country and our people, and
neither do we. -- Georges W. Bush
| |
| Chris F.A. Johnson 2005-11-30, 5:55 pm |
| On 2005-11-30, Mr. Uh Clem wrote:
> Bjorn Reese wrote:
>
> Very true, but he also asked specifically about running find and
> find does not need any help from the shell because find does
> its own filename matching. So I felt it should be pointed out
> that such programs can be directly exec*'d.
>
> It's also worth pointing out that a shell ls command will choke
> if there are too many files in the directory.
Only if you pass all the filenames on the command line. For
example, the first command may fail; the second will not:
ls /path/to/dir/*
ls /path/to/dir/
--
Chris F.A. Johnson, author | <http://cfaj.freeshell.org>
Shell Scripting Recipes: | My code in this post, if any,
A Problem-Solution Approach | is released under the
2005, Apress | GNU General Public Licence
| |
| Chris F.A. Johnson 2005-11-30, 5:55 pm |
| On 2005-11-30, Pascal Bourguignon wrote:
> "Mr. Uh Clem" <uhclem@DutchElmSt.invalid> writes:
>
> You should decide, is it a shell built-in? or is it the ls command?
>
> AFAIK, ls has no other limit on the number of file in a directory than
> the virtual memory size. On a 32-bit system, if you can fill between
> 2GB and 4GB in a directory, ls will happilly load it in memory,
> quicksort them, and print them.
>
>
> On the other hand, shells have been known to have much smaller limits
> on the number, or on the size of the wildcard expansions.
You have it backwards. An external command will fail because of
"Argument list too long" (or similar) before an internal shell
command will fail.
For example:
$ touch
{a,b,c,d}{a,b,c,d}{a,b,c,d,e,f,g}{a,b,c,d}{a,b,c,d}{a,b,c,d}{a,b,c,d} | wc -l
bash: /bin/touch: Argument list too long
0
$ printf "%s\n" {a,b,c,d}{a,b,c,d}{a,b,c,d,e,f,g}{a,b,c,d}{a,b,c,d}{a,b,c,d}{a,b,c,d} | wc -l
28672
--
Chris F.A. Johnson, author | <http://cfaj.freeshell.org>
Shell Scripting Recipes: | My code in this post, if any,
A Problem-Solution Approach | is released under the
2005, Apress | GNU General Public Licence
| |
| Mr. Uh Clem 2005-11-30, 8:49 pm |
| Pascal Bourguignon wrote:
> "Mr. Uh Clem" <uhclem@DutchElmSt.invalid> writes:
>
>
>
> You should decide, is it a shell built-in? or is it the ls command?
<sheepish> I wasn't sure at the time when I posted,
hence the wording. </sheepish> Now I think it
can be either.
> AFAIK, ls has no other limit on the number of file in a directory than
> the virtual memory size. On a 32-bit system, if you can fill between
> 2GB and 4GB in a directory, ls will happilly load it in memory,
> quicksort them, and print them.
And actually, I have seen ls blow up, clearly not the shell:
% find . | wc
18159 18159 163420
% ls
UX:ls: ERROR: Out of memory: Insufficient or invalid memory
And this is with a directory full of files with 6 character
file names on NCR MP-RAS with (I believe) the defaults
for a non-privileged user.
Thanks, Chris, for pointing out that ls can have implied
wildcard behavior without an *, as in the above example
and your examples.
> On the other hand, shells have been known to have much smaller limits
> on the number, or on the size of the wildcard expansions.
Aren't the limits on command line length and number of args well
short of huge? For some reason, 4k args and line lengths on the
order of 16 or 32k sticks in my mind.
--
Clem
"If you push something hard enough, it will fall over."
- Fudd's first law of opposition
|
|
|
|
|