Searching for files that its filename matches a wildcard strings in a directory

Greetings,I am writting a program that simulate cp command in linux. Here's the part code I have so far:
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
int main( int argc, char *argv[] )
{
	if (argc != 3)
	{
		cerr << "Program must take 2 arguments from terminal. Exiting now!" << endl;
		return 1;	// End the program with error.
	}

	char *source = argv[1];
	char *destination = argv[2];

	validateSource(source);

	ifstream infile(source);	
	if (!infile)
	{
		cerr << "Error: Input file could not be opened." << endl;
		return 1;
	}

	infile.seekg(0, infile.end);			
	unsigned int filesize = infile.tellg();	
	infile.seekg(0, infile.beg);			

	char *buffer = new char[filesize];		// Allocate size for buffer.

	infile.read(buffer, filesize);	// Read all the file content into memory.

	string filename;

	getSourceFilename(filename, source);	// Call function to get the source filename.
	
	bool destinationExist;

	int destinationIsValid = open(destination, O_RDONLY);

	if (destinationIsValid < 0)
	{
		destinationExist = false;	
	}
	else
	{
		destinationExist = true;	
	}

	bool sourceIsWildcard;

	sourceIsWildcard = checkIsWildcard(filename);

	bool isDirectoryPath = false;	
	bool isFile = false;	

	// If directory of file exist.
	if (destinationExist)
	{
		checkDestinationIsDirectoryPathOrFile(isDirectoryPath, isFile, destination);

		if (!sourceIsWildcard)
		{
			// User did not enter wildcard for source.
			if(isDirectoryPath)
			{
				string newPath;	

				for (int i = 0; i< strlen(destination); ++i)
				{
					newPath += destination[i];	
				}
				newPath += filename;			

				// Copy files to destination.
				ofstream outfile( newPath.c_str() );		// Create output file stream to create a file and write the contents.
				if (!outfile)
				{
					cerr << "Error: Output file could not be opened." << endl;
					return 1;
				}
				outfile.write(buffer, filesize);	// Write the file content to the file.
			}
			else if(isFile)
			{
				string input;	// Field for confirmation input.
				// Overwrite files.
				cout << "Overwrite " << filename << " ? y/n" << endl;
				getline(cin, input, '\n');	// Read in the user input into the field.
			
				if (input == "y" || input == "Y")	// Case where user choose yes to overwrite.
				{
					// Write to the same file and overwrite its content.
					// Copy files to destination.
					ofstream outfile(destination);	// Create output file stream to create a file and write the contents.
					if (!outfile)
					{
						cerr << "Error: Output file could not be opened." << endl;
						return 1;	// Exit the program with error.
					}
					outfile.write(buffer, filesize);	// Write the file content to the file.
				}
				else if (input == "n" || input == "N")	// Case where user choose not to overwrite.
				{
					return 0; 	// Exit the program without doing anything.	
				}
				else	// Case where user enter anything other than 'y' or 'n'.
				{
					cerr << "Error: Invalid input. Please try again later."	<< endl;		
				}
			}
		}
		// User enter wildcard for source.
		else if (sourceIsWildcard)
		{
			
			// Use regex (regular expression) from regex class in c++ to do the searching and matching of wildcards.
			regex alphanum ("[A-Za-z0-9]+");   // Matches any alphanum.
			// Count how many files match the wildcard result.
		}
	}
	// If directory or file does not exist.
	else
	{
		checkDestinationIsDirectoryPathOrFile(isDirectoryPath, isFile, destination);

		// If destination is a directory path.
		if (isDirectoryPath)
		{
			int status;	// Field for the mkdir function status (success or fail).
			// Make the directory path.
			status = mkdir(destination, S_IRWXU);

			if (status == -1)
			{
				cerr << "Error: Directory path could not be created." << endl;
				return 1;	// Exit with error.
			}

			string newDir;	// Field to store the directory path with the filename.

			for (int i = 0; i < strlen(destination); ++i)
			{
				newDir += destination[i];	// Assign the path to the field.
			}
			newDir += '/' + filename;		// Add the filename to the field.

			// Create another file with the same file name as source and copy over the content.
			ofstream outfile( newDir.c_str() );	// Create output file stream to create a file and write the contents.
			if (!outfile)
			{
				cerr << "Error: Output file could not be opened." << endl;
				return 1;	// Exit the program with error.
			}
			outfile.write(buffer, filesize);	// Write the file content to the file.
		}
		// If destination contain a filename.
		else if (isFile)
		{
			string directory; // Field for directory.

			unsigned int filename_charCount = 0;	// Field to store the number of characters of the filename.
		
			for (int i = strlen(source) - 1; i >= 0; --i)
			{
				if (source[i] != '/')
				{
					++filename_charCount;	// Count increment.
				}
				else
				{
					break;	// Break free from the loop to get the last segment of the directory string.
				}
			}

			// Read the directory by lefting out the filename from the string.
			for (int i = 0; i < strlen(destination) - filename_charCount; ++i)
			{
				directory += destination[i];
			}

			// Create the new directory.
			int status;
			// Create the directory path.
			status = mkdir(directory.c_str(), S_IRWXU);

			if (status == -1)
			{
				cerr << "Error: Directory path could not be created." << endl;
				return 1;	
			}

			// Create another file with the same file name as source and copy over the content.
			ofstream outfile(destination);	
			if (!outfile)
			{
				cerr << "Error: Output file could not be opened." << endl;
				return 1;	// Exit the program with error.
			}
			outfile.write(buffer, filesize);	// Write the file content to the file.
		}
	}
	return 0;
}

void validateSource(char *&source)
{
	// Open function return negative value if error occurs.
	int sourceIsValid = open(source, O_RDONLY);

	if (sourceIsValid < 0)
	{
		cerr << "Source path or file does not existed!" << endl;
		exit(1);	// Exit program with error.
	}

	struct stat st_buf;
	// Get the status of the file system object.
	int status = stat(source, &st_buf);

	if (status != 0) 
	{
		cerr << "Destination file status is bad!" << endl;

		exit(1);	// Exit the program with error if file status is bad.
	}
	
	// Check whether the source is a directory or file. If it is a directory, exit with error.
	if ( S_ISDIR (st_buf.st_mode) ) 
	{
		cerr << "Selected source is not a file!" << endl;
		exit(1);
	}
}

bool checkIsWildcard(string &filename)
{
	// Loop the last segment of source string to search for asterisk character.
	for (int i = 0; i < filename.length(); ++i)
	{
		if (filename.at(i) == '*')
		{
			return true;	// Wildcard is detected.
		}
	}
	return false;	// Not wildcard.
}

void getSourceFilename(string &filename, char *&source)
{
	int filename_charCount = 0;	// Field to store the number of characters of the filename.

	for (int i = strlen(source) - 1; i >= 0; i--)
	{
		if (source[i] != '/')
		{
			++filename_charCount;	// Count increment.
		}
		else
		{
			break;	// Break free from the loop to get the last segment of the directory string.
		}
	}

	for (int i = strlen(source) - filename_charCount; i < strlen(source); ++i)
	{
		filename += source[i];	// Add in all the characters to form the filename.
	}
}
void checkDestinationIsDirectoryPathOrFile(bool &isDirectoryPath, bool &isFile, char *&destination)
{
	int filename_charCount = 0;	// Field to store the number of characters of the filename.

	for (int i = strlen(destination) - 1; i >= 0; i--)
	{
		if (destination[i] != '/')
		{
			++filename_charCount;
		}
		else
		{
			break;
		}
	}

	for (int i = strlen(destination) - filename_charCount; i < strlen(destination); ++i)
	{
		// A filename contain extension indicated by '.'.
		if (destination[i] == '.')
		{
			isFile = true;
		}
	}

	if (!isFile)
	{
		isDirectoryPath = true;
	}
}


I'm currently stuck at processing the wildcard part. I found out about regex but i'm not sure whether that's a good way to do this.

When the user runs "./program /home/user/*.cpp /home/user/results" in the terminal, the program will search for any cpp files in the home directory and copy those file to a folder named "results" in home directory.
1
2
3
4
5
6
#include <iostream>
int main(int argc, char **argv){
   for(int K=0; K<argc; ++K)
      std::cout << K << ' ' << argv[K] << '\n';
   return 0;
}
$ ./a.out *.cpp /home/
0 ./a.out
1 args.cpp
2 list.cpp
3 main.cpp
4 /home/
Last edited on
Thanks for the tips. Appreciate it!
Topic archived. No new replies allowed.