Know how many txt there are in a directory - c

i am trying to do a program that check a directory and tell me how many txt already exist so i can write a new one sequentially.
What is the best way to do that, and how i do that?
Sorry for my poor english

You can use the dirent header to accomplish this task.
you should iterate through every file in the folder, and then you should just do string manipulation, to get the extension of each file.
#include <stdio.h>
#include <dirent.h>
#include <string.h>
int main()
{
const char *dir = ".";//current dir
printf("opening folder\n");
DIR *root_folder = opendir(dir);
if(root_folder == 0) {
printf("Error opening file");
return -1;
}
struct dirent *file;
while((file = readdir(root_folder)) != NULL) {
if(strcmp(file->d_name, ".") == 0 || strcmp(file->d_name, "..") == 0)
continue;
printf("%s\n", file->d_name);
//you can work with the names here
}
}

As Barmar suggested, you can use the functions opendir() to open the desired directory and readdir() to read its content. readdir() returns a pointer to a dirent struct. More about the struct here. You can later use strrchr() to find the last occurence of . and strcmp() to see if you have a match.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
int main(void)
{
int txt_count = 0;
DIR *pdir = NULL;
struct dirent *dp = NULL;
char *dir = "."; /* current directory, modify to match your dir */
char *type = NULL;
pdir = opendir(dir); /* opens directory dir */
if (!pdir) /* check if failed to open */
{
fprintf(stderr, "Can't open dir <%s>\n", dir);
exit(EXIT_FAILURE);
}
while ((dp = readdir(pdir))) /* reading contents until NULL */
{
type = strrchr(dp->d_name, '.'); /* get a pointer to the last occurence of '.' in filename */
if (type != NULL && !strcmp(type, ".txt")) /* compare with ".txt",check type for NULL if not found */
{
txt_count++;
}
}
printf("Total txt files in directory </%s> --> %d\n", dir, txt_count);
return 0;
}

Related

How to compare multiple files based on only file type and size

The goal is to compare files by size and filter those of the same size.
For that you need to compare every file to every file.
However the first loop doesnt work so the search of the first directory is stuck at the first file.
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/stat.h>
int main(int argc, char *v[]) {
struct dirent *d_verzeichnis1;
struct dirent *d_verzeichnis2;
DIR *dir1;
DIR *dir2;
FILE *file = fopen(v[3], "W");
dir1 = opendir(v[1]);
dir2 = opendir(v[2]);
struct stat filesize1;
struct stat filesize2;
while ((d_verzeichnis1 = readdir(dir1)) != NULL) {
stat((d_verzeichnis1->d_name), &filesize1);
while ((d_verzeichnis2 = readdir(dir2)) != NULL) {
stat((d_verzeichnis2->d_name), &filesize2);
if (filesize1.st_size == filesize2.st_size);
{
printf("%s und %s sind gleich\n",
d_verzeichnis1->d_name, d_verzeichnis2->d_name);
}
}
d_verzeichnis1 = readdir(dir1);
}
}
There are multiple problems in your code:
you should verify the actual number of arguments provided on the command line to avoid undefined behavior if fewer than 3 were provided.
fopen(v[3], "W"); uses an invalid mode string, you should use "w". It is unclear what this stream pointer is used for anyway.
dir1 and dir2 are not tested: you have undefined behavior if opendir() fails.
stat is called with the directory entry name, which is not a relative pathname to the file if the directory is different from the current directory. You should construct the path name from the directory name and entry name.
if (filesize1.st_size == filesize2.st_size); has an extra ; at the end of the line, causing the following block to execute unconditionally. You should use K&R style with{` at the end of the line to avoid such silly mistakes.
the logic of parallel scan is incorrect: you should reopen or at least rewind the second directory for each entry in the first to allow a full scan for potential matches.
Here is a corrected version:
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>
char *buildpath(char *dest, size_t size, const char *dir, const char *name) {
size_t len = strlen(dir);
const char *sep = "";
if (len > 0 && dir[len - 1] != '/')
sep = "/";
if ((unsigned)snprintf(dest, size, "%s%s%s", dir, sep, name) < size)
return dest;
else
return NULL;
}
int main(int argc, char *argv[]) {
char path1[1024];
char path2[1024];
struct dirent *dp1;
struct dirent *dp2;
DIR *dir1;
DIR *dir2;
struct stat filesize1;
struct stat filesize2;
if (argc < 3) {
fprintf(stderr, "missing argument\n");
fprintf(stderr, "usage: cmpdir dir1 dir2\n");
return 1;
}
dir1 = opendir(argv[1]);
if (dir1 == NULL) {
fprintf(stderr, "cannt open directory %s: %s\n", argv[1], strerror(errno));
return 1;
}
dir2 = opendir(argv[2]);
if (dir2 == NULL) {
fprintf(stderr, "cannt open directory %s: %s\n", argv[2], strerror(errno));
return 1;
}
while ((dp1 = readdir(dir1)) != NULL) {
/* ignore . and .. entries */
if (!strcmp(dp1->d_name, ".")
|| !strcmp(dp1->d_name, ".."))
continue;
if (!buildpath(path1, sizeof path1, argv[1], dp1->d_name)) {
/* path too long */
continue;
}
if (stat(path1, &filesize1)) {
/* cannot stat entry */
continue;
}
if (!S_ISREG(filesize1.st_mode)) {
/* not a regular file */
continue;
}
rewinddir(dir2);
while ((dp2 = readdir(dir2)) != NULL) {
/* ignore . and .. entries */
if (!strcmp(dp2->d_name, ".")
|| !strcmp(dp2->d_name, ".."))
continue;
if (!buildpath(path2, sizeof path2, argv[2], dp2->d_name)) {
/* path too long */
continue;
}
if (stat(path2, &filesize2)) {
/* cannot stat entry */
continue;
}
if (!S_ISREG(filesize2.st_mode)) {
/* not a regular file */
continue;
}
if (filesize1.st_size == filesize2.st_size) {
printf("%s and %s have the same size %llu\n",
path1, path2, (unsigned long long)filesize1.st_size);
/* perform actual comparison... */
}
}
}
closedir(dir1);
closedir(dir2);
return 0;
}

how to find the files with .done extension from a specific directory using c language

int main(int argc, char **argv)
{
char *dirFilename = "/home/sv5071184/sample";
DIR *directory = NULL;
directory = opendir (dirFilename);
if(directory == NULL)
return -1;
struct dirent *dirp;
while ((dirp = readdir (directory)) != NULL) {
if( ! (strcmp (dirp->d_name ,".done") == 0) )
{
printf ("%s\n", dirp->d_name);
}
}
if(closedir(directory) < 0)
return -1;
}
NOTE: i have updated the code . with this code am able to find all the files in a directory whereas i need to find only .done files
The function char *strstr(const char *haystack, const char *needle); give you the position of the substring 'needle' if exists. Then you just have to test if the substring is at the end of the file name.
EDIT:
If you want to keep your code as you did, in the while, change your if condition to:
strstr(dirp->d_name, ".done")!=NULL
Here is how you can find the extension using strrchr:
#include <string.h>
int main(int argc, char **argv)
{
char *dirFilename = "/home/sv5071184/sample";
DIR *directory = NULL;
directory = opendir (dirFilename);
if(directory == NULL)
return -1;
struct dirent *dirp;
while ((dirp = readdir (directory)) != NULL) {
char *dot = strrchr(dirp->d_name, '.'); /* Find last '.', if there is one */
if (dot && (strcmp(dot, ".done") == 0))
{
printf ("%s\n", dirp->d_name);
}
}
if(closedir(directory) < 0)
return -1;
}
Finding files that end in specific string (an extension) is very common thing to do with file names.
For the better or worse, under POSIX standard, file name is not separated into name and extension , and unfortunately C string library does not have a function that is like endsWith in Java or C#.
I think that you should write a simple utility function ends_with(char*, char*) that checks if one string ends with another and use it to check if ends_with(ent->d_name, ".done").
Hope this helps :)
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <dirent.h>
int main(int argc, char **argv)
{
char *dirFilename = "/home/sv5071184/sample";
DIR *directory = NULL;
directory = opendir (dirFilename);
if(directory == NULL)
return -1;
struct dirent *dirp;
while ((dirp = readdir (directory)) != NULL) {
if ( strstr(dirp->d_name , ".done" ))
{
printf( "found a .done file: %s\n", dirp->d_name );
}
}
if(closedir(directory) < 0)
return -1;
}
I have used this way and it is working.. thanks everyone

C: S_ISDIR not working properly, only the "." and ".." show up as directories

For some reason when I iterate through all the files/folders in a directories, and check my current selection against S_ISDIR it only works on the "." and the ".." directories. Even though I have 3 files (A, B, C) and 2 folders (subdir, seconddir)
code:
//will read all files inside current directory, logic steps down into any sub directory found
int readDir(char * opt_basedir) // opt_basedir is the folder within the root repository of the .exe file, in this case "test"
{
struct dirent *dirr;
DIR *directory; // used to keep track of current directory
struct stat fileStat; //used for lstat to hold stat info for the document
directory = opendir("."); // open root
directory = opendir(opt_basedir); // iterate straight into the selected folder
dirr = readdir(directory);
while(dirr){
lstat(dirr->d_name, &fileStat);
if(S_ISDIR(fileStat.st_mode))
{
printf("only prints of . and .. =>" );
}
//if file (open)
//readCopy(opt_basedir, &block, &offset);
// else folder
//function call
printf("%s\n",dirr->d_name);
dirr = readdir(directory);
}
}
Not sure what I'm doing wrong here... :(
You must make sure first that opt_basedir is your current working directory.
You could do something like
chdir(opt_basedir);
directory = opendir(".");
instead of
directory = opendir(opt_basedir);
Another way is to create an absolute path:
directory = opendir(opt_basedir);
/* error check */
while ((dirr = readdir(directory))) {
char *path = malloc(strlen(opt_basedir) + strlen(dirr->d_name) + 1);
/* error check */
strcpy(path, opt_basedir);
strcat(path, dirr->d_name);
lstat(path, ...);
/* other code */
free(path);
}
Here is a full test program (Note: the output in readDir() only for debugging):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
void
readDir(const char *path)
{
DIR *dp;
struct dirent *dr;
struct stat fs;
dp = opendir(path);
if (dp == NULL) {
perror("opendir");
return;
}
printf("%s:\n", path);
while ((dr = readdir(dp))) {
if (!strcmp(dr->d_name, ".") || !strcmp(dr->d_name, "..")) {
continue;
}
char *abs_path = malloc(strlen(path) + strlen(dr->d_name) + 2);
if (!abs_path) {
perror("malloc");
exit(EXIT_FAILURE);
}
strcpy(abs_path, path);
strcat(abs_path, "/");
strcat(abs_path, dr->d_name);
if (lstat(abs_path, &fs) < 0) {
free(abs_path);
continue;
}
if (S_ISDIR(fs.st_mode)) {
readDir(abs_path);
}
printf("\t%s\n", dr->d_name);
free(abs_path);
}
}
int
main(int argc, char *argv[])
{
if (argc != 2) {
fprintf(stderr, "Usage: %s dir\n", argv[0]);
exit(EXIT_FAILURE);
}
readDir(argv[1]);
exit(EXIT_SUCCESS);
}
Besides d_name, struct dirent has a member called d_type, too.
Then to fulfill your task, just do sth. like:
struct dirent * dirr;
DIR * directory = opendir(opt_basedir);
if (directory) {
while ((dirr = readdir(directory)) != nullptr) {
if (DT_DIR == dirr->d_type) {
...
}
}
...
}
... is any code you may want to add. And here DT_DIR helps you to check whether it is a directory or not. You don't need to use stat() or S_ISDIR or so on. (Since you already used dirent)
Hope this answer will help you and anybody else who have similar problem.

file->d_name into a variable in C

I have a probleme with a program.
I need to take file name in a folder and put it in a variable.
I tried that:
#define _POSIX_SOURCE
#include <dirent.h>
#include <errno.h>
#include <sys/types.h>
#undef _POSIX_SOURCE
#include <stdio.h>
int main()
{
DIR *dir;
struct dirent *file;
char fileName;
dir = opendir("../../incoming");
while ((file = readdir(dir)) != NULL)
printf(" %s\n", file->d_name);
fileName = file->d_name;
printf(fileName);
closedir(dir);
return 0;
}
thx
Not very clear what you wanted, I prefer to think you want read the file name into your varible 'fileName' and then handle that varible...
Correct 2 parts:
fileName type should be same as the struct member for assign.
the while loop......
int main(){
DIR *dir;
struct dirent *file;
char fileName[255];
dir = opendir("../../incoming");
while ((file = readdir(dir)) != NULL)
{
printf(" %s\n", file->d_name);
strncpy(fileName, file->d_name, 254);
fileName[254] = '\0';
printf("%s\n", fileName);
}
closedir(dir);
return 0;
}
You need to declare a character array of sufficient size and copy the contents of the file->d_name into it if you want to save it past the call to closedir().
If you want to simply print the name,
printf("%s\n", file->d_name);
would accomplish that.

Storing bmp filename into an array

I have to store the bmp filename in an array.
eg: files in the current directory
a.bmp b.bmp c.txt d.bmp xyz.exe ...
Currently my output is:
fname[0]=.
fname[1]=..
fname[2]=a.bmp
fname[3]=b.bmp
fname[4]=c.txt
fname[5]=d.bmp
fname[6]=xyz.exe
desired output:
fname[0]=a.bmp
fname[1]=b.bmp
fname[2]=d.bmp
Here is my code.
#include <stdio.h>
#include <dirent.h>
#include <string.h>
int main(int argc, char **argv)
{
char filename[20][256];
DIR *dir;
int i=0,k;
struct dirent *ent;
dir = opendir ("D:\\font\\");
if (dir != NULL)
{
/* print all the files and directories within directory */
while ((ent = readdir (dir)) != NULL)
{
strcpy(filename[i],ent->d_name);
i++;
/* save filenames in the array */
}
closedir (dir);
}
for (k=0;k<i;k++)
printf("%s\t %d\n",filename[k],k);
FILE *fp;
if(!(fp=fopen(filename[i],"rb")))
{
//file handling
}
fclose(fp);
return 0;
}
However, this code save all the files of current directory in the array. Could someone help me out how to store only bmp filename in the array?
try using strstr function; here is a reference for it.
char* str2 = ".bmp";
strstr(filename[i],str2);
This will return NULL for all filenames you don't care about.
This will work only if the file names are in the form of *.* .
You have to check ent->d_name before adding to your array. You can do in your while loop using strrchr and strcmp for example
char *pdot = strrchr(ent->d_name, '.');
if (dot && !strcmp(pdot, ".bmp")) {
strcpy(filename[i], ent->d_name);
i++;
}
Also if you need case case-insensitive string comparisons use strcasecmp instead of strcmp
You're accessing filename[i] at a position, where you haven't copied anything at position i (fopen line, but increased recently at the strcpy line). Be carefull (I commented the affected code out).
To compare the sufix of your c-strings you could use strcmpi() if available (it's not part of ISO-C), but because you're using dirent already which is not part of ISO-C also (but in the POSIX) you probably want to use strcasecmp().
#include <stdio.h>
#include <dirent.h>
#include <string.h>
int main(int argc, char **argv){
char filename[20][256];
DIR *dir;
int i=0,k;
struct dirent *ent;
dir = opendir ("D:\\font\\");
if (dir != NULL){
/* print all the files and directories within directory */
while ((ent = readdir (dir)) != NULL){
size_t offset = strlen(ent->d_name)-4;
if((strlen(ent->d_name) >= 4) && (!strcasecmp(ent->d_name[offset], ".bmp"))){
strcpy(filename[i],ent->d_name);
i++;
/* save filenames in the array */
}
}
closedir (dir);
}
for (k = 0; k < i; k++) {
printf("%s\t %d\n",filename[k],k);
}
/*FILE *fp;
if(!(fp=fopen(filename[i],"rb"))){
//file handling
}
fclose(fp);*/
return 0;
}

Resources