the ls -ali output will be treated like a string input for the c++ program i need to write.

i have tried to output ls -ali command into a txt file and below is the output of the ls -ali:

-rwxr--r-- 1 User1 root 26 Nov2 19:51 Mydb.txt

basically, the first column is the permissions of the file , like writable permission or read only permission.

and the second column will be the directories and the third column will be the user ...etc.

The problem here is i dun know how to write my c++ problem to sum up how many files are writable permission file and also to show the user name ...etc.

Basically is how c++ read column? Not that i didn't try to write the code, i seriously need some kick start ...i have no idea how to read column!

Recommended Answers

All 6 Replies

Consider instead...

- using opendir() to open a directory
- using readdir() in a loop to get each directory entry
-- using stat() on each entry to get the permissions
-- evaluate those permissions as you want
- using closedir() when you're done.

I'm no linux guru, but i think you could redirect the output of ls to a file within a system() call. I forget how to do this in *nix but in windows it would be something like:

dir > file.txt

Then this file can be opened for input and parsed. The only problem with using system calls is portability. But if you're testing linux specific commands then I'm sure windows users won't expect it to run anyway.

Now to actually parse it, I would sugguest making some sort of struct with members that you want to load in, then instead of loading in columns, load them one word at a time (left to right) into the respective struct members (most likely an array of a struct). Since this data will always have the same format (if not tampered with) parsing shouldn't be that difficult to do.

struct sFiles
{
     char * _szFilename;
     char * _szPath;
     //i forget how many attributes linux filesystems use
     bool    _attrtibuteFlag[4];
     //have some more crap here for other stuff you want to load
};

int main();
{
     //this should probably be dynamically allocated...
     sFiles Files[255];
     int i(0);
     char * tmpIn;
     //assuming the file fFileIn has been declared and opened for input
    while (!fFileIn.eof() && !fFileIn.fail() && i < 255)
     {
          //I don't actually have any idea which order this stuff is saved
          //so this probably won't quite work right.
          i++;
          fFileIn.getline(tmpIn, 255, '\n');
          for (int ii(0); ii < strlen(tmpIn); ++ii)
          {
                  //parsing code goes here
                 //looking for various flags which 
                 //indicate the end of input
                 //ie a space after the path+filename
                 // would indicate the end
                 //of the path/filename.  Then the 
                 //last \ before the space indicates
                 //the start of the filename only,
                 //with the path preceeding it
                 
                //i'm not actually testing this code,
                //and don't have much time...so I'll
                //leave the hard part up to you (this code)
          }
     } 
}
struct sFiles
{
     char _szFilename[255];
     char _szPath[255];
     //i forget how many attributes linux filesystems use
     bool    _attrtibuteFlag[4];
     //have some more crap here for other stuff you want to load
};

int main();
{
     //this should probably be dynamically allocated...
     sFiles Files[255];
     int i(0), iStage(0);
     char * tmpIn;
     //assuming the file fFileIn has been declared and opened for input
    while (!fFileIn.eof() && !fFileIn.fail() && i < 255)
     {
          //i dont really have any idea what the file would look like in 
          //linux, so this is just a general rough idea of what to do
          i++;
          iStage = 0;
          fFileIn.getline(tmpIn, 255, '\n');
          for (int ii(0); ii < strlen(tmpIn); ++ii)
          {
                  switch (iStage)
                  {
                  case 0:
                          if (tmpIn[i] == ' ')
                          {
                              iStage++
                              break;
                          }
                          Files[i]._szPath[ii] = tmpIn[i];
                          break;
                 case 1:
                  //parsing code goes here
                 //looking for various flags which 
                 //indicate the end of input
                 //ie a space after the path+filename
                 // would indicate the end
                 //of the path/filename.  Then the 
                 //last \ before the space indicates
                 //the start of the filename only,
                 //with the path preceeding it
                 
                //i'm not actually testing this code,
                //and don't have much time...so I'll
                //leave the hard part up to you (this code)
          }
     } 
}

There's a more helpful version of the above code, but don't try to copy + paste it, as it won't compile. I kind of just left off in the switch (parsing) statement. The rest is up to you.

This would be so much easier to parse out using scripting :).

If you are going to parse the output of ls -al, keep in mind that your permissions, are for the root, the group and the user. And the preceeding "d" indicates whether that is a directory or not. So you will need to separate those, and if you are only interested in the user level permissions, save those and drop the rest.

513062 -rwxrwxrwx+ 1 smith dev 10876 May 16 9:42 part2

Your first column is the i-node for this file, the column indicates that you have a file where the user, group and other permissions are rwx respectively. The next indicates column the # of files in that directory. the next 2 columns indicate the user and the group that own this file. The next is the total number of bytes in the file, then the timestamp when the file was last modified, followed by the file name.

Lets say you redirect your ls -al contents to a file (ls -al > contents). You can then open your contents file and read in the values into a list of some sort. Each object in the list may have the following elements. The only values you will really need to parse out are the permissions and perhaps the timestamp. The rest of it is pretty standard and you should just be able to read it in.

class myLsContents{
    private:
      unsigned int inode;
      string permissions;
      bool isDirectory;    
      int    dirFiles;
      string username;
      string groupname;
      string filesize;
      // object to store the timestamp;
      string filename;
   }

'Skatamatic', what u mean is, write a loop to read each character and then when it bum into a space, it means a new column? I can't really do that right, cos looking at the time stamp, there is a space between nov2 19:51

'stillearning' , do u mean the same things when u said reading in the values into the list?

What I meant was you can create a class or a structure to store the attributes for each line. Then you can add that to a list. That way at the end of your file read, you will have a list of objects, where each object has the attributes for a file. Then you can go ahead and do your summations etc.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.