7

How can I check if a file exists in my directory before continuing with my program? I have read answers that try opening the file using various methods but my issue is that most of the time, the file I am checking for will be corrupt and cant be opened. This happens in the error checking part of my program and will only be triggered when an error in the preceding code has occurred. I want to check if the file exists, if so then ask to delete it, otherwise just print out some message.

How can I go about this?

(Just deleting and accepting the errors would work, but I'm doing this to learn, so I want to do it properly...)

Edit:

I have downloaded Boost to use the filesystem library and have compiled it, seemingly with no errors, but when I try to compile my program, I get this response:

g++ program.cpp -I <path to>/boost_1_54_0 -o output

Undefined symbols for architecture x86_64:
"boost::filesystem::detail::status(boost::filesystem::path const&, boost::system::error_code*)", referenced from:
  boost::filesystem::exists(boost::filesystem::path const&)in cc1XX8rD.o
"boost::system::system_category()", referenced from:
  __static_initialization_and_destruction_0(int, int)in cc1XX8rD.o
"boost::system::generic_category()", referenced from:
  __static_initialization_and_destruction_0(int, int)in cc1XX8rD.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status

The only places I use boost in the program are:

boost::filesystem::path my_file(s4);
if (boost::filesystem::exists(my_file)){ ...
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
sion
  • 1,367
  • 6
  • 17
  • 21
  • Can you not simply (try to) delete the file anyway and tolerate any errors triggered by the deletion attempt in case it didn't exist? – Walter Aug 07 '13 at 10:06

4 Answers4

5

Use stat() or access():

#include <unistd.h>

int res = access(path, R_OK);
if (res < 0) {
    if (errno == ENOENT) {
         // file does not exist
    } else if (errno == EACCES) {
         // file exists but is not readable
    } else {
         // FAIL
    }
}
greybeard
  • 2,249
  • 8
  • 30
  • 66
David Xu
  • 5,555
  • 3
  • 28
  • 50
3

A file that exists but contains corrupt data can be opened with no ill effect. As long as you don't try to read the contents of the file.

However, any "check if it exists" is subject to TOCTUI and is quite unnecessary in the first place. Just trying to delete the file and accept that deletion may not always work is a better approach.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
2

If, by any chance, you're using Boost in your project, you could go with Boost.Filesystem:

#include <boost/filesystem.hpp>

boost::filesystem::path my_file("some/path/some_file");

if (boost::filesystem::exists(my_file))
{
    boost::filesystem::remove(my_file);
}
else
{
    std::cout << "File does not exist!" << std::endl;
}

This solution is portable across many systems Boost.Filesystem Implementation.

  • That looks quite good but I don't think I want the whole lot of Boost files. Would it slow me down if every time I run a command, Terminal has to search through all of those files to see if the binary is there? The zipped file is over 50MB so I assume there are a fair few binaries in there. I may be completely wrong, if so, I'll download and install it all... – sion Aug 07 '13 at 12:59
  • I downloaded Boost but I can't get it to work. I compiled just the filesystem library, added the boost_1_54_0/stage/lib directory to my PATH, included the boost_1_54_0 directory with the -I flag when compiling with g++, included in my code but I still can't get it to work. See the edit to my original post for the errors I'm getting. Does it not work with my processor or am I just doing something wrong? – sion Aug 07 '13 at 14:48
  • g++ program.cpp -I /boost_1_54_0 -L/boost_1_54_0/lib -lboost_filesystem -lboost_system -o output – Mateusz Kołodziejski Aug 07 '13 at 15:06
  • That compiled fine but when i run it, it gives this error `dyld: Library not loaded: libboost_filesystem.dylib Referenced from: Reason: image not found Trace/BPT trap: 5` Do I have to include additional arguments when running the code? – sion Aug 08 '13 at 10:51
  • It seems that your boost library cannot be found in any system path by your program. You can workaround that with: export DYLD_LIBRARY_PATH=/path/to/boost/lib:$DYLD_LIBRARY_PATH – Mateusz Kołodziejski Aug 08 '13 at 10:54
  • Can't I just place these files in the directories that g++ already uses? And then I could use it as easily as including the normal libraries (e.g. iostream, string, vector etc). I dont have to include any extra arguments to use them or add any directories to search, why can't I put the boost files where those others are kept? – sion Aug 08 '13 at 15:09
  • You have to explicitly deploy Boost "somewhere". You could deploy it along with your application using proper directory structure - so you always have the same Boost Lib version in your program. Or you could just install Boost in your system and link against it - http://stackoverflow.com/questions/104322/how-do-you-install-boost-on-macos – Mateusz Kołodziejski Aug 09 '13 at 12:31
  • Why do I have to link to it every time I compile something that uses it? Why can't I put it into the directory that the system searches anyway so that I can just use it like any other default library (ie `g++ -o output`)? I installed the whole lot with homebrew but it seems I still have to compile using those linking options – sion Aug 09 '13 at 14:01
  • That's because they are separate libraries. The default library is automatically linked against, so you don't have to write -lstd etc., and it's present on every system. Boost is a 3rd party library which needs to be installed separately. Most programs that you use everyday are made of such 3rd party libraries which are installed separately - either bundled with an application, or installed in some other way - and they are explicitly linked against using -llib param during compilation/linking. – Mateusz Kołodziejski Aug 09 '13 at 18:13
-3

You want to do that without try to open. If you change your mind and try to open the file:

bool file_exists(std::string filename){
   ifstream ifile(filename);
   return ifile;
}

Somebody says, that this will close automatically. I don't know.

And, if you don't want to open the file, I think there is a lots of opportunities. I can tell a slow, oldschool and ugly solution, maybe others will tell you better solutions. Here it is:

system("dir > something.abc");

After that, you have to open something.abc file, and parse / interpreter the lines. You have to open something.abc file, but, you don't have to open that file, which's you want to analize.

This solution will be very slow (0.5 seconds, this is not good for example with 100 files), you have to write a lots of code, and this will be very complecated to parse / interpreter the "dir" command's answer.

  • I included the `file_exists` function that you gave and then did `if(file_exists(s4)==true){ //the file exists } else{ //it doesn't exist }` but it always seems to think the file doesn't exist, even when it does. Have I done something wrong? – sion Aug 07 '13 at 12:24
  • This is awful. Please see the other answers. – Jim Balter Aug 04 '17 at 18:11