C 程序不在声明的目录路径中工作,仅在当前目录中

C 程序不在声明的目录路径中工作,仅在当前目录中,c,system-calls,C,System Calls,我正在编写一个程序,从命令行中声明的目录中获取所有文件。命令行有两个参数,目录路径和一个可选标志“-s”,如果应用,该标志将按非降序显示目录信息。我已经完成了90%,但我的程序只从当前目录中吐出文件和文件信息,而不是命令行中指定的目录。如有任何建议,将不胜感激 #include <stdio.h> #include <stdlib.h> #include <dirent.h> #include <unistd.h> #include <fcn

我正在编写一个程序,从命令行中声明的目录中获取所有文件。命令行有两个参数,目录路径和一个可选标志“-s”,如果应用,该标志将按非降序显示目录信息。我已经完成了90%,但我的程序只从当前目录中吐出文件和文件信息,而不是命令行中指定的目录。如有任何建议,将不胜感激

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <string.h>
#include <ctype.h>

int mygetFstat(char *name);
char *removeWhiteSpaces(char *str);

#define PATH 1
#define FLAG 2
#define LEN 10
#define STRLEN 54
#define MAXLEN 100

    struct stat fileStat;
    time_t t;
    struct tm lt;
    char timbuf[MAXLEN];

int main(int argc, char *argv[]){

DIR *dir;
struct dirent *ent;
FILE *ptr;
char myBuf[MAXLEN]; 
char filename[MAXLEN];
 char finalfile[MAXLEN]; 
char length;
 char str[MAXLEN];
 char cmd[MAXLEN];


if ((dir = opendir (argv[PATH])) != NULL) {
  // print all the files and directories within directory

   if(argv[FLAG] != NULL){
     if(strcmp(argv[FLAG], "-s") == 0){
       system("ls -al | sort -k5n >> tempfile.txt");

       //sprintf(finalfile, "cd %s | ls -al | sort -k5n >> tempfile.txt", (char *)argv[PATH]);
       // printf("\nfinal file = %s\n", finalfile);
       //    system(finalfile);

        if(NULL == (ptr = fopen("tempfile.txt","rw"))){
         printf("\nCan't open file.\n");
          exit(1);
        }

        while(!feof(ptr)){             // loop through every line in tempfile.txt
      fgets(myBuf, MAXLEN, ptr);
      if(strlen(myBuf) > LEN){     // I chose 11 here because some lines were only 10 characters
                                   // And they were unnecessary. 

      length = strlen(myBuf);      // Grabs length of entire line from ptr

      strncpy(filename, myBuf + STRLEN, length);           // the file names start at bit position 54, 
      if((filename[0] == '.') && (filename[1] != '.') && (strlen(filename) != 2)){
        removeWhiteSpaces(filename);
        mygetFstat(filename); 
      }
     }
    }
    system("rm tempfile.txt");
        exit(1);

     }else{
       printf("Error: Flag not recognized.\n");
       return 0;
     }
    }else{

    while((ent = readdir(dir)) != NULL){
      if((ent->d_name[0] == '.') && (ent->d_name[1] != '.') && (strlen(ent->d_name) != 1))
    mygetFstat(ent->d_name);

    }
  closedir (dir);  
  }
    } else {
  // could not open directory

   printf("No such File or Directory.\n");
    return EXIT_FAILURE;
    }
}

int mygetFstat(char *name)
{
  // Function for finding info about files.

    int file = 0;
        if((file = open(name,O_RDONLY)) < -1)
            return 1;

    if(fstat(file,&fileStat) < 0)
        return 1;

    printf("Information for %s\n",name);
    printf("---------------------------\n");
    printf("File Size: \t\t%d bytes\n",fileStat.st_size);

    // Adjusts time to display date. Not just seconds from epoch

    t = fileStat.st_mtime;
    localtime_r(&t, &lt);
    strftime(timbuf, sizeof(timbuf), "%c", &lt);
    printf("Date Last Modified: \t%s\n",timbuf);
    printf("\n");

    //return 0;
}

char *removeWhiteSpaces(char *str){ //removes white spaces from input
  char *end;
  while(isspace(*str)) str++;
  if(*str == 0)
    return str;

  end = str + strlen(str)-1;
  while(end > str && isspace(*end)) end--;
  *(end+1) = 0;
  return str;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int mygetFstat(字符*名称);
char*removewitespaces(char*str);
#定义路径1
#定义标志2
#定义LEN 10
#定义STRLEN 54
#定义MAXLEN 100
struct stat fileStat;
时间;
struct-tm-lt;
char timbuf[MAXLEN];
int main(int argc,char*argv[]){
DIR*DIR;
结构导向;
文件*ptr;
char myBuf[MAXLEN];
字符文件名[MAXLEN];
字符最终文件[MAXLEN];
字符长度;
char-str[MAXLEN];
char cmd[MAXLEN];
if((dir=opendir(argv[PATH])!=NULL){
//打印目录中的所有文件和目录
如果(argv[FLAG]!=NULL){
如果(strcmp(argv[FLAG],“-s”)==0){
系统(“ls-al | sort-k5n>>tempfile.txt”);
//sprintf(最终文件,“cd%s | ls-al | sort-k5n>>tempfile.txt”,(char*)argv[PATH]);
//printf(“\n最终文件=%s\n”,最终文件);
//系统(最终文件);
if(NULL==(ptr=fopen(“tempfile.txt”、“rw”)){
printf(“\n无法打开文件。\n”);
出口(1);
}
而(!feof(ptr)){//则遍历tempfile.txt中的每一行
fgets(myBuf、MAXLEN、ptr);
如果(strlen(myBuf)>LEN){//我在这里选择了11,因为有些行只有10个字符
//它们是不必要的。
length=strlen(myBuf);//从ptr获取整行的长度
strncpy(filename,myBuf+STRLEN,length);//文件名从位54开始,
如果((文件名[0]='。)&&(文件名[1]!='。)&&(strlen(文件名)!=2)){
删除空白(文件名);
mygetFstat(文件名);
}
}
}
系统(“rm tempfile.txt”);
出口(1);
}否则{
printf(“错误:无法识别标志。\n”);
返回0;
}
}否则{
while((ent=readdir(dir))!=NULL){
如果((ent->d_名称[0]='.)&(ent->d_名称[1]!='.)&&(strlen(ent->d_名称)!=1))
mygetFstat(ent->d_名称);
}
closedir(dir);
}
}否则{
//无法打开目录
printf(“没有这样的文件或目录。\n”);
返回退出失败;
}
}
int mygetFstat(字符*名称)
{
//用于查找有关文件的信息的函数。
int file=0;
如果((文件=打开(名称,仅限))<-1)
返回1;
if(fstat(file,&fileStat)<0)
返回1;
printf(“用于%s\n的信息”,名称);
printf(“------------------------------------\n”);
printf(“文件大小:\t\t%d字节\n”,fileStat.st\u Size);
//调整显示日期的时间。而不仅仅是从历元开始的秒数
t=fileStat.st_mtime;
本地时间(r&t,<);
strftime(timbuf,sizeof(timbuf),%c',<);
printf(“上次修改日期:\t%s\n”,timbuf);
printf(“\n”);
//返回0;
}
char*removeWhiteSpaces(char*str){//从输入中删除空白
字符*结束;
而(isspace(*str))str++;
如果(*str==0)
返回str;
end=str+strlen(str)-1;
而(end>str&&isspace(*end))end--;
*(结束+1)=0;
返回str;
}

ent->d_name
仅包含该目录中条目的名称。它不包括条目的完整路径

如果第一个参数是“folder1”,并且该目录中有文件“file-1.txt”和“file-2.txt”,则
ent->d_name
将是“file-1.txt”和“file-2.txt”。您需要将“folder1/file-1.txt”传递到
mygetFstat()
,而不仅仅是“file-1.txt”

您应该将
while
循环更改为:

while((ent = readdir(dir)) != NULL){
   if((ent->d_name[0] == '.') && (ent->d_name[1] != '.') && (strlen(ent->d_name) != 1))
   {
      strcpy(filename, argv[PATH]);
      strcat(filename, "/");
      strcat(filename, ent->d_name);
      mygetFstat(filename);
   }
}
while((ent = readdir(dir)) != NULL){
  if ( is_dot_or_dot_dot(ent->d_name) )
  {
     continue;
  }
  strcpy(filename, argv[PATH]);
  strcat(filename, "/");
  strcat(filename, ent->d_name);
  mygetFstat(filename);
}
更新

我将添加一个函数

int is_dot_or_dot_dot(char const* entryName)
{
   return (strcmp(entryName, ".") == 0) || (strcmp(entryName, "..") == 0);
}
并将
while
循环中的代码更改为:

while((ent = readdir(dir)) != NULL){
   if((ent->d_name[0] == '.') && (ent->d_name[1] != '.') && (strlen(ent->d_name) != 1))
   {
      strcpy(filename, argv[PATH]);
      strcat(filename, "/");
      strcat(filename, ent->d_name);
      mygetFstat(filename);
   }
}
while((ent = readdir(dir)) != NULL){
  if ( is_dot_or_dot_dot(ent->d_name) )
  {
     continue;
  }
  strcpy(filename, argv[PATH]);
  strcat(filename, "/");
  strcat(filename, ent->d_name);
  mygetFstat(filename);
}

保留代码,在打开目录后立即执行chdir:

if ((dir = opendir (argv[PATH])) != NULL) {
// print all the files and directories within directory
    // Change the working directory to the one given.
    if (chdir(argv[PATH]) == -1) { 
         perror(argv[PATH]); exit(1);
     }
另外,我建议使用perror,但你必须包括errno.h

对其余代码的改进

       system("ls -al | sort -k5n >> tempfile.txt");
虽然您可以这样做,但将其插入到链表中并在插入时对其进行排序将是一种更快的方法。但如果您想保留它,请参见下面的改进

这个项目的全部要点是使用系统调用

feof不可靠,请使用

       while( fgets (myBuf, MAXLEN, ptr)!=NULL ){ 

我理解你的逻辑,我感谢你的回答。但我无法让您的代码段正常工作。当我运行它时,它保持堆芯转储。我是个白痴。忽略该评论^^^感谢您的输入此操作非常有效@用户3600601很高兴它起作用了。我仍然对
if
语句感到困惑。你是想说忽略
?是的!我不想要当前目录(.)和上一个目录(..)的信息,所以我用if排除这些信息。此外,如果您在这一行有任何输入:system(“ls-al | sort-k5n>>tempfile.txt”);我不太擅长unix命令,这只返回当前目录中的文件,而不是目录路径。再多给点建议就好了。非常感谢。