How to use the system command

I am trying to use the system() to open the command prompt. I want to copy all txt files in F:/AMBIENT/grid into one txt file. I am using the following command. This is opening the cmd prompt but not opening the F: or coping files into one file. I think I am doing some error in putting the syntax in the system().

1
2
3
4
5
6
7
8
9
10
  #include<stdio.h>
#include<iostream>
using namespace std;
void main()
{
	
	system("start cmd.exe F:/AMBIENT/grid copy *.txt new.txt");

system("pause");
}
closed account (28poGNh0)
Do you want to copy a *.txt located in F:/AMBIENT/grid ,am I right?
the command prompt is another shell that can be used to do system commands.

system("something"); is the same thing as typing "something" into the command prompt, or putting "something" in a .bat file.

That being said, I think the command: copy *.txt new.txt is not going to work. try it in the command prompt first, but I think that new.txt will just be a copy of the last .txt file in the current folder.

I think what you want is:
echo *.txt >> new.txt I think that echo will display the contents of each .txt file in your console. The > will redirect the output to new.txt. The >> will ensure that it appends the current file.

In a system command this would look like this (though I can't test it because I'm on Linux).
system("echo *.txt >> new.txt");

That being said, NEVER use system. You can do the same thing with the <fstream> library. If you really wanted to be windows specific, you could use the WinAPI <windows.h>. The system command is so bad that some anti-virus software will flag your exe as a virus if it's used too often. Let's say I have a file "echo.exe" in the current directory. Well instead of actually running the intended "echo", we've just run some random executable. That's not good! We have no idea what just happened. Your code may look like it worked properly, but you may have also just uploaded your documents to some pirate's FTP.
copy does support wild cards, but you need to ensure the copy target doesn't match the wild card or you'll end up with 2 x the expected output (as the last action of type will be to copy the latest file, new.txt, into new.txt.)

copy *.txt new.foo && rename new.foo *.txt

And type is the command you need, not echo. Same deal for name wrt to the wildcard.

But, as Stewbond has already mentioned, you should be using system in the first place...

Andy

PS As echo and type are actual shell commands, sneaking an exe file with these names into a folder on the path (or your local directory) has no effect. But cmd.exe and copy.exe are another matter.
Last edited on
@Stewbond
You ought to try it out or read some docks before saying anything. The cmd.com copy command will concatentate all source files into the destination, so OP's copy command works just fine.

@tatai
The problem is that you need to read the documentation for start. (Sorry)

1
2
3
4
5
6
7
#include <cstdlib>
using namespace std;

int main()
  {
  system("start /d foo /wait /b %ComSpec% /c copy *.txt new.txt >nul 2>&1");
  }

You really could do it very easily in pure C++ though, and avoid all the problems with system().

Hope this helps.
¿is consistency too much to ask?
\> copy i?.txt test\new.txt
i1.txt
i2.txt
i3.txt
i4.txt
   1 files copied

\> copy i1.txt i2.txt i3.txt i4.txt test\new.txt
The syntax of the command is incorrect

\> copy i1.txt+i2.txt + i3.txt+i4.txt test\new.txt
i1.txt
i2.txt
i3.txt
i4.txt
   1 files copied


> copy does support wild cards
I thought that it was the shell that expands them, before passing it as arguments to the program
Last edited on
Yes, but cmd.exe is actually pretty smart about trying to copy a file into itself.
Instead of using the system() i have tried the same like this
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include<iostream>
#include<fstream>
#include<sstream>


using namespace std;
void main()
{
	
	for(int i=1; i<6; i++)
	{
stringstream sum;
sum<<"summary_"<<i<<".out";
string summary= sum.str();
	
	ifstream normal(summary);
	ofstream newfile("new.txt");

	newfile<<normal.rdbuf();
	
	}



system("pause");

}


but it is not running properly. just taking the output form summary_1.out in the new.txt!! I think there is problem with the FOR loop!!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <fstream>
#include <sstream>
#include <string>

int main() // main must return int
{
    constexpr int NFILES = 6 ;
    const std::string prefix = "summary" ;
    const std::string ext = ".out" ;

    // open thoe output stream once, right at the beginning
    std::ofstream newfile( "new.txt" ) ;

    for( int file_num = 1 ; file_num < NFILES ; ++file_num ) // for each onput file
    {
        std::ostringstream sum ;
        sum << prefix << file_num << ext ;
        newfile << std::ifstream( sum.str() ).rdbuf() ;

        // or if your compiler supports it:
        // newfile << std::ifstream( prefix + std::to_string(file_num) + ext ).rdbuf() ;

    }
}
> copy does support wild cards
I thought that it was the shell that expands them, before passing it as arguments to the program

copy is a shell command, not a program, so there's no copy.exe. The copy shell command does support wild cards.

xcopy.exe is program though, and it also supports wild cards.

But the Windows command interpreter (cmd.exe, aka command prompt) isn't that helpful. And that's where system() calls end up (the system function eventually calls CreateProcess with "cmd.exe /c <your command>", after much faffing about with search paths, file extensions, etc.)

("shell" is more often used to refer to Explorer in Windows-speak, rather than the command prompt. Though both are part of the shell in the looser sense.)

C:\Test>test.exe *.* *.txt test.* test?.txt
argc = 5
argv[0] = test.exe
argv[1] = *.*
argv[2] = *.txt
argv[3] = test.*
argv[4] = test?.txt


1
2
3
4
5
6
7
8
9
10
#include <iostream>
using namespace std;

int main (int argc, char* argv[]) {
    cout << "argc = " << argc << "\n";
    for (int i = 0; i < argc; ++i) {
        cout << "argv[" << i << "] = " << argv[i] << "\n";
    }
    return 0;
}


Andy
Last edited on
Just tried your example and the arguments do expand before being send to my program.
Just tried your example and the arguments do expand before being send to my program.

Well, this thread is clearly about running an app on Windows using the standard command console, going by the mention of cmd.exe, etc.

So if the behaviour you are describing is when running an app in another environment then I don't see how it is relevant other than as an aside. In which case it would be have been more helpful if you had stated which environment you were using.

I did state that the behaviour I was talking about was specific to the Windows command console.

Andy
Last edited on
windows xp
Ah, Ok.

I happen to be using Windows XP, too. (As well as Windows 7 and Windows 8)

You're prob building with GCC ??

It's the CRT which is doing the expansion for you, not the command interpreter.

You can persuade exes built with MSVC to do the same, by linking with setargv.obj to override the default, stupid behaviour.

I didn't realised GCC defaulted in the opposite direction... (is this because it pretending that the app is running in a Bash shell or something?)

Edit: I assume it's a default. But I'm finding it had to track down how to disable this behaviour. There are times when I want a program to be in control of the wild card processing.

Andy

Is there any way to get the windows cmd shell to expand wildcard paths?
http://superuser.com/questions/460598/is-there-any-way-to-get-the-windows-cmd-shell-to-expand-wildcard-paths

To summarise: no!

Expanding Wildcard Arguments
http://msdn.microsoft.com/en-us/library/8bch7bkk.aspx

re. use of setargv.obj
cl typeit.c /link setargv.obj
Last edited on
@andywestken
Found it.

http://mingw-users.1079350.n2.nabble.com/Problems-with-expanding-wildcards-to-a-program-td1358555.html

To disable MinGW's automatic wildcard expansion, link CRT_noglob.o (found in ~/lib) with your program.

:O)
I don't think anyone else mentioned this but it is int main and not voidmain.
@Duoas

Thanks -- something to file away for possible future use.

Andy
I actually had to find this thread because you had said something about it, because I'm using it right now.

I'm messing with an old program I wrote that accepts MS-style help requests (foo /?), but that was failing, and when I printed out the value of argv[1] it was giving me the one root file with a single letter...

And I was confused, because I knew the shell did not do command-line argument expansion...

So now that I've learned how to fix it I can compile properly. :O)
Topic archived. No new replies allowed.