How to use wildcards with argv

This is a personal project not related to school work.

I have a program that works like the dos find command, except mine shows line numbers in the output. What mine doesn't do is work with wild cards.

To start it I type:
// works like the dos find command but with line numbers
find2 "String" "Filename.ext"
or
// works like the dos type command but with line numbers
find2 "" "Filename.ext"


I"m using
int main(int argc, char* argv[])

I have seen post about using regex, but don't have boost yet, will try and get that after this post and I just came across this today.
It has example code but I haven't figured it out.
http://msdn.microsoft.com/en-us/library/aa364418(VS.85).aspx

I am hoping to see example code that works with wild cards, using one of these or something else. If you have it, I really appreciate the help. I learn best that way.

I would like to be able to type:
find2 "String" "Filename*.txt"


-Thx-
Last edited on
¿grep?
find2 "" "*.txt"
If that's supposed to mean `find empty lines in all txt' then you don't need to do anything especial.
The expansion *.txt to parse all the files is a task of the shell, you will simply receive as several args

Try
1
2
3
for(int K=0; K<argc; ++K)
   std::cout << argv[K] << ' ';
std::cout << std::endl;
If you get rid of the quotes will not the terminal handle the wildcards automatically so that your program doesn't have to do anything special? I mean if you run your program as find2 *.txt will you not get all the .txt files in the current working directory stored in argv[1], argv[2], ..., argv[argc-1]?
Sorry this is on Windows, no grep.
The quotes are optional and there to handle spaces because dos takes anything after a space as a different argument.

ne555
your for loop only takes the number of command line arguments and increases argv by one. How is that supposed to affect the filename ?

Peter87
argv[0] is the command you type
argv[1] is the search string, to define a empty string type "", this works to find all lines, not just empty ones.
argv[2] is the filename
and no typing
find2 xyz *.txt
doesn't work, I wish it was that easy.

> Sorry this is on Windows, no grep.
I want to know if it's the same behaviour (and you can easily install grep)

> your for loop only takes the number of command line arguments and increases argv by one
No, my code shows the arguments that your program receives.


> find2 xyz *.txt
> doesn't work, I wish it was that easy.
It does work, it's that easy
It does work, it's that easy


No, it doesn't.

1
2
3
4
5
6
7
#include <iostream>

int main( int argc, char* argv[])
{
    for ( unsigned i=0; i< argc; ++i )
        std::cout << argv[i] << '\n' ;
}
C:\Users\Cire\Documents\Visual Studio 2012\Projects\Junk\Debug\Junk.exe
*.txt


Last edited on
So you need to check for existence too, interesting.
Just as planned.
Last edited on
I think if you use a terminal to run it, the shell should unravel the names for you. I am currently actually working on this, I will post here if mine works. You can try making a function that replaces all * with the actual filenames. No such functions come to mind, but you can play around with it and see what happens.

E.
Try these libraries :
1
2
#include <sys/types.h> 
#include <dirent.h>  
Last edited on
I just did some very basic testing using std::regex and the tr2 filesystem stuff, but the following seems to work.

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <iostream>
#include <fstream>
#include <regex>
#include <filesystem>

void replace_all( std::string& source, char replace, const std::string& replacement )
{
    unsigned pos = 0 ;
    while ( pos < source.length() && std::string::npos != (pos = source.find(replace, pos)) )
    {
        source.replace(pos, 1, replacement) ;
        pos += replacement.length() ;
    }
}

std::string to_regex_expression(const std::string& path)
{
    std::string expression("^" + path) ;

    replace_all(expression, '.', "\\.") ;
    replace_all(expression, '*', ".*") ;
    replace_all(expression, '?', "(.{1,1})") ;

    return expression ;
}

namespace fs = std::tr2::sys ;

std::vector<fs::path> generate_paths(char const* pattern)
{
    std::vector<fs::path> results ;

    if ( std::string::npos == std::string(pattern).find_first_of("*?") )
    {
        if ( fs::exists(fs::path(pattern)) )
            results.emplace_back(pattern) ;
        return results ;
    }

    std::regex expr(to_regex_expression(pattern), std::regex_constants::icase) ;

    for ( auto it = fs::directory_iterator(".") ; it != fs::directory_iterator() ; ++it )
    {
        if (std::regex_match(it->path().filename(), expr))
            if ( fs::is_regular_file(it->path()) )
                results.push_back(it->path()) ;
    }
    return results ;
}


template <typename T>
void print( const std::vector<T>&v )
{
    for ( auto & path : v )
        std::cout << path << '\n' ;
}


int main( int argc, char * argv[])
{
    if ( argc > 1 )
    {
        std::vector<fs::path> files = generate_paths(argv[1]) ;
        print(files) ;
    }
}
Topic archived. No new replies allowed.