views:

53

answers:

2

If I want to pass a program data files how can I distinguish the fact they are data files, not just strings of the file names. Basically I want to file redirect, but use command line arguments so I can a sure input is correct.

I have been using:

./theapp < datafile1 < datafile2 arg1 arg2 arg3 > outputfile

but I am wondering is it posible for it to look like this:

./the app datafile1 datafile2 arg1 arg2 arg3 > outputfile

Allowing the use of command line arguments.

+3  A: 

It's a little hard to combine two files into standard input like that. Better would be:

cat datafile1 datafile2 | ./theapp arg1 arg2 arg3 >outputfile

With bash (at least), the second input redirection overrides the first, it does not augment it. You can see that with the two commands:

cat <realfile.txt </dev/null # no output.
cat </dev/null <realfile.txt # outputs realfile.txt.

When you use redirection, your application never even sees >outputfile (for example). It is evaluated by the shell which opens it up and connects it to the standard output of the process you're trying to run. All your program will generally see will be:

./theapp arg1 arg2 arg3

Same with standard input, it's taken care of by the shell.

The only possible problem with that first command above is that it combines the two files into one stream so that your program doesn't know where the first ends and second begins (unless it can somehow deduce this from the content of the files).

If you want to process multiple files and know which they are, there's a time-honoured tradition of doing something like:

 ./theapp arg1 arg2 arg3 @datafile1 @datafile2 >outputfile

and then having your application open and process the files itself. This is more work than letting the shell do it though.

paxdiablo
+1  A: 

From the perspective of your program, all command line arguments are strings, and you have to decide whether they represent file names or not yourself. There are only two bytes that cannot appear in a file name on Unix: 0x00 and 0x2F (NUL and /). [I really mean bytes. Except for HFS+, Unix file systems are completely oblivious to character encoding, although sensible people use UTF-8, of course.]

Shell redirections don't appear in argv at all.

There is a convention, though: treat each element of argv (except argv[0] of course) that does not begin with a dash as the name of a file to process, in the order that they appear. You do NOT have to do any unquoting operations; just pass them to fopen (or open) as is. If the string "-" appears as an element of argv, process standard input at that point until exhausted, then continue looping over argv. And if the string "--" appears in argv, treat everything after that point as a file name, whether or not it begins with a dash. (Including subsequent appearances of "-" or "--").

There may be a handy library module or even a language primitive to deal with this stuff for you, depending on what language you're using. For instance, in Perl, you just write

for (<>) {
   ... do stuff with $_ ...
}

and you get everything I said in the "There is a convention..." paragraph for free. (But you said C, so, um, you gotta do most of it yourself. I'm not aware of an argument-processing library for plain C that's worth the space it takes on disk. :-( )

Zack