windows mingw asterisk '*' passing by argv[1] to string
Asked Answered
W

2

0

I wrote a code below

#include<stdio.h>

int main(int argc, char *argv[]) {
    char cmd[50]="dir";
    if (argc == 2) {
        sprintf(cmd,"dir %s",argv[1]);
    }
    if (argc == 3) {
        sprintf(cmd,"dir %s %s", argv[1], argv[2]);
    }
    printf("%s\n",cmd);
    system(cmd);
    return 0;
}

when I executed like below

enter image description here

I think can't pass '*' by *argv[]

How can I pass something like "*.c" ?

update

code

#include<stdio.h>

int main(int argc, char *argv[]) {
    char cmd[50]="dir";
    if (argc == 2) {
        sprintf(cmd,"dir %s",argv[1]);
    }
    if (argc == 3) {
        sprintf(cmd,"dir %s %s", argv[1], argv[2]);
    }
    if (argc > 3) {
        sprintf(cmd,"dir %s %s", argv[1], argv[2]);
    }
    printf("%s\n",cmd);
    system(cmd);
    return 0;
}

changing is below enter image description here

what..... @.@ ?

Updated code again

#include<stdio.h>
#include<string.h>

int main(int argc, char *argv[]) {
    int i;
    char sp[2]=" ", cmd[250]="dir";
    if (argc > 1) {
        sprintf(cmd,"dir /d ");
        for (i =1 ; i < argc; i ++)  {
            strcat(cmd,sp);
            strcat(cmd,argv[i]);
        }
    }
    printf("%s\n",cmd);
    system(cmd);
    return 0;
}

see what happen when I executed

enter image description here

kind of ugly.... any decent idea?

Whortleberry answered 22/11, 2015 at 21:1 Comment(17)
I tried this on my Windows system (compiled with gcc from MinGW) and *.c is passed correctly.Borrell
edit your code to include if (argc > 3) case. Probably shell expansion is occurringSierrasiesser
@Borrell but mine don't correctly. :(Whortleberry
@Sierrasiesser I add if (argc > 3) case. ls *.c converting to dir cat.c copycon.c what ....what's going on?Whortleberry
@Whortleberry post your updated code and screenshot, make sure you are running the updated codeSierrasiesser
What shell are you using? Can you try ls "*.c"Jone
@Jone the shell is cmd.exe (windows 10)Whortleberry
What happens if you quote "*.c" ?Jone
@Sierrasiesser I think buffer holds all of *.c strings. what do you think?Whortleberry
@Whortleberry the updated version shows that the argc > 3 case is actually happeningSierrasiesser
try echo *.c. Does it display *.c or the list of C files?Jone
@Jone echo *.c shows that *.c the same.Whortleberry
So it seems that cmd.exe is doing shell expansion on Windows 10, this doesn't happen on my system Windows 8.1Borrell
It would be surprising that Microsoft would introduce such a drastic change in Windows 10. That would cause endless headaches as so many batch and command files rely on the previous behavior. I suspect the C runtime is doing the expansion. See this question: #3995993Jone
@Jone "*.c" ... this is working well what I expected. but uglyWhortleberry
This will complicate your quick and dirty implementation of ls. Especially since the stupid dir command cannot handle multiple arguments gracefully.Jone
The ugly output is that of dir. You cannot implement a decent ls as a wrapper on top of such a braindead CMD.EXE built-in command. You will need to write some substantial amount of non trivial code to implement the ls unix utility. If you just care about a single filespec, try to find a different toolchain that does not expand wildcards, such as Microsoft Visual Studio (I never thought I would ever give such advice!)Jone
J
3

This issue is not related to the C runtime, but to the shell behaviour. If you use Windows CMD.EXE, the * is passed unchanged to the programs, whereas if you use Cygwin's bash, the shell expands * to the list of files and passes this expansion as individual arguments to your program. You can prevent this expansion by quoting the wildcards with "*" or '*'.

Note that you should not use sprintf, but snprintf to avoid buffer overflows. If you link to the non standard Microsoft C library, you may need to use _snprintf instead.

EDIT: CMD.EXE does not seem to expand wildcards, but the C runtime you link your program with might do it at startup. See this question: Gnuwin32 find.exe expands wildcard before performing search

The solution is to quote the argument.

Jone answered 22/11, 2015 at 21:12 Comment(3)
The OP seems to be using CMD.EXE. Cygwin would show the path as /cygdrive/d/systemPlication
He might be use a more advanced Windows shell that expands wildcards... Quoting the argument should fix the problem.Jone
@Jone "quoting" helps but ugly, I just have to use the powershell. thank you for helping me once of all.Whortleberry
L
1

I'm afraid the accepted answer is not correct as the edit courteously admits. What is happening here is that globbing behaviour is provided in the C runtime but the default behaviour differs between compilers.

Yes, it's a major pain if you do not know what is happening. Worse the globbing does not occur if the glob does not match any files. I was pretty surprised myself.

Under Visual Studio, by default, wildcards are not expanded in command-line arguments. You can enable this feature by linking with setargv.obj or wsetargv.obj:

cl example.c /link setargv.obj

Under MinGW, by default, wildcards are expanded in command line arguments. To prevent this you can link with CRT_noglob.o or, much more easily, add the global variable:

int _CRT_glob = 0; 

in your own source in the file which defines main() or WinMain().

Lakeishalakeland answered 29/6, 2016 at 11:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.