List files on a directory on C - c

I am starting to learn c and i need a little help understanding this code:
#include "apue.h"
#include <dirent.h>
int main(int argc, char *argv[])
{
DIR *dp;
struct dirent *dirp;
if (argc != 2)
err_quit("usage: ls directory_name");
if ((dp = opendir(argv[1])) == NULL)
err_sys("can't open %s", argv[1]);
while ((dirp = readdir(dp)) != NULL)
printf("%s\n", dirp->d_name);
closedir(dp);
exit(0);
}
So, i know that the first if will tell you that you are missing the directory from which you want to list the files, but i´m totally lost with the next if and the while, which i know that will print the files but i fail to understand the conditions of the while, any help would be appreciated, thanks!

If condition will open main directory from which you want to read files.It will return NULL if it fails to open it.
Second , while condition will read files from given directory one by one and printing name of files.
readdir will read first file form directory and and will return NULL if it fails in reading file.
So in while condition if readdir is successfully read file then it will not return NULL.So now condition becomes like while(dirp != NULL).

Related

usage of tmpfile() in C

I don't understand why my script below seems to work without creating any files.
script.c:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[]){
printf("P_tmpdir is '%s'\n", P_tmpdir);
FILE *tmp = tmpfile();
if(tmp == NULL){
printf("Unable to create temp file");
exit(1);
}
else{
printf("Temporary file is created\n");
}
for(int i = 0; string[i] != '\0'){
fputc(string[i], tmp);
}
rewind(tmp);
while(!feof(tmp)){
putchar(fgetc(tmp));
}
sleep(3);
return(0);
}
The P_tmpdir variable returns me the "/tmp" directory although in the sleeping time no new file is created in it... can you help me or explain me plz ?
Quoting cppreference.com (emphasis mine):
On some implementations (e.g. Linux), this function actually creates, opens, and immediately deletes the file from the file system: as long as an open file descriptor to a deleted file is held by a program, the file exists, but since it was deleted, its name does not appear in any directory, so that no other process can open it.
The file does not have to be "visible" in the file system tree, as long as a process has a handle on it, the file continues to exist.
If you want a file that's visible in the file system tree you should use mkstemp.

C use of dirent.h

Final update- Answer is in the comments of the accepted answer.
First of all I realize there are a lot of other answers to this question. I've been through most of them and this code is a combination of going through many other answers. All I want to do is get to the full path to every file in a directory.
#include <limits.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
DIR *d;
struct dirent * dir;
char fullpath[PATH_MAX + 1];
d = opendir("/home/adirectory");
if(d != NULL)
{
while((dir = readdir(d)) != NULL)
{
realpath(dir->d_name, fullpath);
printf("[%s]\n", fullpath);
printf("%s\n", dir->d_name);
}
// addition of the following line yields
// Value too large for defined data type
perror("Something isn't working: ");
closedir(d);
}
return 0;
}
Update #3:
The call that fails is dir = readdir(d), which is why I have perror
immediately after the while loop.
Update #2:
This works just fine on CentOS, and Ubuntu gcc 4.8.5 +. Does not work on
Solaris gcc 4.5.2.
Update:
There is an error message:
Value too large for defined data type
...but I'm not sure what could cause this.
This always just prints the current working directory that I'm running the program from. Even so, it doesn't actually list any of the files in that directory besides "." and ".." . What gives? Is there some kind of permission issue? Does this solution not work in 2017?
the d_name field contains the name of the file in the context of the directory it traverses. So, it does not contain any path, just the name.
So, in order for you to play with its path, you need to append the d_name to the name of the directory, something like the following:
char *myHomeDir = "/home/adirectory";
d = opendir(myNomDir);
. . .
while((dir = readdir(d)) != NULL) {
char filepath[PATH_MAX + 1] ;
strcpy(filepath, myHomeDir);
strcat(filepath, "/");
strcat(filepath, dir->d_name);
realpath(filepath, fullpath);
Of course the stuff above is just a skeleton code for clarity. It could be optimized better and you should use strncpy family of functions.

How to read data from all files in a directory using C Language?

I am trying to 1) Find all files in a directory and display them, 2) Open all found files and read data from them (characters) 3) Output the read data to the screen or a new file.
This is done in C Language and you will see below my current code. The problem that I am running into is that: I can find all the files in my directory and print them to the screen just fine (point 1 above), but when I try to open the found files and read data (characters) from them (point 2 above), I get a segmentation fault.
If I comment out the fscanf(entry_file, "%s", files); line below, but leave the entry_file = fopen(in_file->d_name, "r"); line, it compiles okay and writes the files to the screen. I also tried indexing the fscanf line with the int i (not shown below) and produced the same segmentation fault.
So, how can I read data from these found files? Thanks!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <errno.h>
int main()
{
DIR* dir;
FILE *entry_file;
struct dirent *in_file;
char files[1000];
int i;
dir = opendir("/Users/tcn/data");
if(dir==NULL){
printf("Error! Unable to read directory");
exit(1);
}
while( (in_file=readdir(dir)) != NULL) {
if (!strcmp (in_file->d_name, "."))
continue;
if (!strcmp (in_file->d_name, ".."))
continue;
printf("%s\n", in_file->d_name);
entry_file = fopen(in_file->d_name, "r");
fscanf(entry_file, "%s", files);
}
closedir(dir);
fclose(entry_file);
return 0;
}
Seeing as you are correctly checking for NULL against dir and in_file before using them, the only other thing that could possibly be causing this is entry_file being null. Check it before using it:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <errno.h>
int main()
{
DIR* dir;
FILE *entry_file;
struct dirent *in_file;
char files[1000];
int i;
dir = opendir("/Users/tcn/data");
if(dir==NULL) {
printf("Error! Unable to read directory");
exit(1);
}
while((in_file=readdir(dir)) != NULL) {
if (!strcmp (in_file->d_name, "."))
continue;
if (!strcmp (in_file->d_name, ".."))
continue;
printf("%s\n", in_file->d_name);
entry_file = fopen(in_file->d_name, "r");
if (entry_file != NULL) {
fscanf(entry_file, "%s", files);
/* whatever you want to do with files */
fclose(entry_file);
}
}
closedir(dir);
return 0;
}
Note also that, as multiple other users have commented, you should close entry_file within the loop.
The two most likely causes of the crash are not checking the return value of fopen – then either the fscanf or the fclose may crash when attempting to use entry_file when it's NULL – and the potential overflow of files.
Another problem which does not cause a crash is that the in_file->d_name does not contain the full path, but only the name of the file. So if you are testing the code inside /Users/tcn/data then it will appear to work, but it will fail elsewhere. Either prefix the filename with /Users/tcn/data/ or operate only on the current directory (.).
Fixes:
if ((entry_file = fopen(in_file->d_name, "r"))) {
(void) printf("%s\n", in_file->d_name);
if (fgets(files, sizeof files, entry_file)) { // or `while`?
// do something with `files`, it will be overwritten for next file
}
(void) fclose(entry_file);
}
And remove the other fclose(entry_file) from the end of the code.
Also note that if you use this code with an arbitrary directory, it might contain pipes and/or device nodes that will hang forever when you attempt to read them.
You will need a function with a loop using fread() to replace the fscanf line, and do a hex dump. For one thing, you don't know if the files are text files or binary files. For another, the segfault could be coming from reading a binary file that contains no newline into char files[1000]; And even if the files are all text files, you cannot predict that your "generous" 1000 length is enough to hold the first line of text.

How do I print the values of every file in a directory in C?

I'm not sure how I'm supposed to read the files in a directory. When I call my print function it segfaults. Can someone help out? I think it has something to do with the path name but I don't know how to go about fixing it.
I know it's not something wrong with my print function because it prints regular files just fine.
int main(int argc, char **argv){
DIR *d;
struct dirent *dir;
d = opendir(argv[1]);
FILE *fp;
if(d){
while((dir = readdir(d)) != NULL){
if(strcmp(dir->d_name, ".") == 0)
continue;
if(strcmp(dir->d_name, ".." == 0)
continue;
fp = fopen(dir->d_name, "r");
//print function on fp
}
}
return 0;
}
You must append dir->d_name to argv[1] (with a '/' of course) to create the full path to the file. Otherwise, you can only open files in the current directory. Alternatively, you can use chdir to change the current directory to argv[1].
To avoid the segfault, you should check the return value from fopen. In fact, you should always check the return value from fopen, because it fails often, especially during development.

Print out file names and its' sizes in C

I'm not sure if C can do this, but I'm hoping that I can make a program that will look into a directory, and print out all of the contents of the directory along with the file size of each file. As in I wanted it to look like this (possibly):
filename.txt -- 300 bytes
filename2.txt -- 400 bytes
filename3.txt -- 500 bytes
And so on.
So far, I created a program that can open a file, and it will print the bytes, but it does not read the entire directory, and I have to be specific with which file I want to read.. (which is not what I want).
Here is what I have so far:
#include <stdio.h>
int main(){
FILE *fp; // file pointer
long fileSize;
int size;
// opens specified file and reads
fp = fopen( "importantcommands.txt", "rw" );
if( fp == NULL ){
printf( "Opening file error\n" );
return 0;
}
// uses fileLength function and prints here
size = fileLength(fp);
printf( "\n Size of file: %d bytes", size );
fclose(fp);
return 0;
}
int fileLength( FILE *f ){
int pos;
int end;
// seeks the beginning of the file to the end and counts
// it and returns into variable end
pos = ftell(f);
fseek (f, 0, SEEK_END);
end = ftell(f);
fseek (f, pos, SEEK_SET);
return end;
}
Please help.
C can certainly do it - the ls(1) command can, for example, and it's written in C.
To iterate over a directory, you can use the opendir(3) and readdir(3) functions. It's probably easier to just let the shell do it for you, though.
As far as getting the filename, you can just take it as a command line parameter by defining main as:
int main(int argc, char **argv)
Command line parameters will begin at argv[1].
See opendir() / fdopendir() and readdir() if you are using linux in dirent.h
man page
Simple example from a : SO Post
DIR *dir;
struct dirent *ent;
if ((dir = opendir ("c:\\src\\")) != NULL) {
/* print all the files and directories within directory */
while ((ent = readdir (dir)) != NULL) {
printf ("%s\n", ent->d_name);
}
closedir (dir);
}
else {
/* could not open directory */
perror ("Could not open directory");
return EXIT_FAILURE;
}
Also You can use the fstat() system call which can fill in the struct stat for any file you want. From that stat you can access that file's size.
Please use the man pages to help you out. (Almost) Everything related to Linux is insanely well documented.
To read a list of files in a directory look at opendir, readdir, closedir for Linux
use stat to get the length of the file.
These are of Linux
For winodws see http://msdn.microsoft.com/en-gb/library/windows/desktop/aa365200%28v=vs.85%29.asp and the link http://blog.kowalczyk.info/article/8f/Get-file-size-under-windows.html will show you how to do this.
To get the list of files in a directory look for "libc opendir". To get the size of a file without opening it you can use fstat.
This seems strangely similar to another question I saw recently. Anyway, here's my strangely similar answer (for Linux, not sure how it'll fare on Windows 7):
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
int main(int argc, char *argv[]) {
struct stat file_stats;
DIR *dirp;
struct dirent* dent;
dirp=opendir("."); // specify directory here: "." is the "current directory"
do {
dent = readdir(dirp);
if (dent)
{
printf("%s -- ", dent->d_name);
if (!stat(dent->d_name, &file_stats))
{
printf("%u bytes\n", (unsigned int)file_stats.st_size);
}
else
{
printf("(stat() failed for this file)\n");
}
}
} while (dent);
closedir(dirp);
}
There are little things need to be taken care for the given examples (under Linux or other UNIX).
You properly only want to print out the file name and size of a regular file only. Use S_ISREG() to test the st_mode field
If you want to recursively print out all files under sub directories also, you then need to use S_ISDIR() to test for direcotry and be carefull of special directory '.' and '..'.

Resources