Thread: How to tell if a input is file or directory

  1. #1
    Registered User
    Join Date
    May 2022
    Posts
    2

    How to tell if a input is file or directory

    Hi, I am a beginner at C programming, and I want to tell if the input is a file or a directory. Here is my code so far:
    Code:
    #include <stdio.h>#include <sys/stat.h>
    
    
    #define ERRMSG "\e[1;91mError:\e[0m "
    #define USAGE "\nUsage: thing [filename]"
    
    
    int err(unsigned char message, char args[])
    {
        if(message == 0)
        {
            printf("%stoo few arguments%s", ERRMSG, USAGE);
        }
        
        if(message == 1)
        {
            printf("%stoo many arguments%s", ERRMSG, USAGE);
        }
        
        if(message == 2)
        {
            printf("%sfile \"%s\" not found", ERRMSG, &args[0]);
        }
        
        if(message == 3)
        {
            printf("%s\"%s\" is a directory", ERRMSG, &args[0]);
        }
        puts("");
        return 1;
    }
    
    
    int main(int argc, char* argv[])
    {
        FILE *fptr;
        fptr = fopen(argv[1], "r");
        
        if(argc < 2)
        {
            err(0, NULL);
        }
        else if(argc > 2)
        {
            err(1, NULL);
        }
        else if(fptr == NULL)
        {
            err(2, argv[1]);
        }
        return 0;
    }
    I know that you nee to use stat, but I do not know how to use it to detect if it is a file or directory. I am using linux.

  2. #2
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  3. #3
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    Found a better link; or at least my eyes thinks the info is easy to read; seems to have the same info on it.
    fstat(2) — Arch manual pages

    Tim S.
    Last edited by stahta01; 05-19-2022 at 08:03 AM.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  4. #4
    Registered User
    Join Date
    Dec 2017
    Posts
    1,628
    Your "err" routine is pointless.
    And you need to check argc before accessing argv[1].
    \e is a non-standard escape sequence. Better to use \033 or \x1b.
    Code:
    #define _POSIX_C_SOURCE 200809L
    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <sys/stat.h>
     
    #define ERRMSG "\033[1;91mError:\033[0m "
    #define USAGE  "Usage: thing FILENAME\n"
     
    int main(int argc, char **argv)
    {
        if (argc != 2)
        {
            printf(ERRMSG USAGE);
            exit(EXIT_FAILURE);
        }
     
        FILE *fin = fopen(argv[1], "r");
        if (!fin)
        {
            printf(ERRMSG "file \"%s\" not found\n", argv[1]);
            exit(EXIT_FAILURE);
        }
     
        struct stat st;
        fstat(fileno(fin), &st);
        if ((st.st_mode & S_IFMT) == S_IFDIR)
        {
            printf(ERRMSG "\"%s\" is a directory\n", argv[1]);
            exit(EXIT_FAILURE);
        }
     
        if ((st.st_mode & S_IFMT) != S_IFREG)
        {
            printf(ERRMSG "\"%s\" is not a regular file\n", argv[1]);
            exit(EXIT_FAILURE);
        }
     
        printf("\"%s\" is a regular file\n", argv[1]);
        fclose(fin);
     
        return 0;
    }
    A little inaccuracy saves tons of explanation. - H.H. Munro

  5. #5
    Registered User rstanley's Avatar
    Join Date
    Jun 2014
    Location
    New York, NY
    Posts
    1,110
    Please don't use die.net for any reliable manpage information. Their manpages are very out of date. Please use man7.org as their pages are generated from the manpage source files and are always up to date. Please see the link below for the current information:

    stat(2) - Linux manual page

  6. #6
    Registered User
    Join Date
    May 2022
    Posts
    2
    Quote Originally Posted by john.c View Post
    Your "err" routine is pointless.
    I made it a function to avoid redundancy, because I might use the same error message in the future.
    Quote Originally Posted by john.c View Post
    And you need to check argc before accessing argv[1].
    Thanks for telling me, I didn't notice it.
    Quote Originally Posted by john.c View Post
    \e is a non-standard escape sequence. Better to use \033 or \x1b.
    I'll make sure to fix that too. What is the difference between these three escape sequences?
    Also, thanks for the example code.

    EDIT:
    Here is my updated code:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/stat.h>
    
    
    #define ERRMSG "\033[1;91mError:\033[0m "
    #define USAGE "\nUsage: thing [filename]"
    
    
    int err(unsigned char message, char args[])
    {
        if(message == 0)
        {
            printf("%stoo few arguments%s", ERRMSG, USAGE);
        }
        
        if(message == 1)
        {
            printf("%stoo many arguments%s", ERRMSG, USAGE);
        }
        
        if(message == 2)
        {
            printf("%sfile \"%s\" not found", ERRMSG, &args[0]);
        }
        
        if(message == 3)
        {
            printf("%s\"%s\" is a directory", ERRMSG, &args[0]);
        }
        if(message == 4)
        {
            printf("%s\"%s\" is not a normal file", ERRMSG, &args[0]);
        }
        puts("");
        exit(EXIT_FAILURE);
    }
    
    
    int main(int argc, char* argv[])
    {
        FILE *fptr;
        
        if(argc < 2)
        {
            err(0, NULL);
        }
        else if(argc > 2)
        {
            err(1, NULL);
        }
        
        fptr = fopen(argv[1], "r");
        
        if(fptr == NULL)
        {
            err(2, argv[1]);
        }
        
        struct stat st;
        fstat(fileno(fptr), &st);
        
        if ((st.st_mode & S_IFMT) == S_IFDIR)
        {
            err(3, argv[1]);
        }
        
        if ((st.st_mode & S_IFMT) != S_IFREG)
        {
            err(4, argv[1]);
        }
        
        fclose(fptr);
        return 0;
    }
    I am still using the err function for the reasons stated above.
    Last edited by teal; 05-19-2022 at 03:33 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Listing files in a user input specified directory
    By BigLe2e in forum C Programming
    Replies: 5
    Last Post: 07-20-2013, 01:01 PM
  2. Replies: 1
    Last Post: 12-06-2012, 02:46 PM
  3. Replies: 6
    Last Post: 04-30-2010, 06:13 PM
  4. Determine if input is file or directory
    By JizJizJiz in forum C++ Programming
    Replies: 20
    Last Post: 06-29-2006, 12:51 AM
  5. File Input/Output Path Directory
    By tegwin in forum C++ Programming
    Replies: 7
    Last Post: 02-27-2002, 03:00 PM

Tags for this Thread