【问题标题】:How to show symbolic links like LS -al?如何显示像 LS -al 这样的符号链接?
【发布时间】:2019-08-26 13:10:47
【问题描述】:

我创建了一个粗略的程序,它使用 C 打印出与 ls -al 类似的提示。虽然它几乎可以完美地工作,除了无法动态打印出无法打开的目录,因为没有参数鉴于它只是在当前目录中运行,所以我认为. 就足够了,但如果有更好的方法来动态地做到这一点,请告诉我。我想知道如果下面显示了任何类似的文件,您如何打印出文件的符号链接。

代码

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <grp.h>
#include <time.h>
#include <pwd.h>
#include <errno.h>
#include <string.h>

int main(void)
{
    DIR *mydir;
    DIR *thedir;
    struct dirent *myfile;
    struct stat myStat;
    struct passwd *pwd;
    int size = 0;
    struct tm lt;
    char buf[1024];
    char length[100];
    long width;
    struct group *gf;
    int len = 0;
    mydir = opendir("./");
    thedir = opendir("./");
    if(mydir!= NULL){
    while((myfile = readdir(thedir)) != NULL){
        lstat(myfile->d_name, &myStat);
        size += myStat.st_blocks;
        width = (long)myStat.st_size;
        sprintf(length, "%ld", width);
        if(len < strlen(length)){
        len = strlen(length);
     }

    }

    printf("total %d\n", size/2);
    closedir(thedir);

    while((myfile = readdir(mydir)) != NULL)
    {

        lstat(myfile->d_name, &myStat);
        if((lstat(myfile->d_name, &myStat) ) == 0){
            pwd = getpwuid(myStat.st_uid);
        }
        gf = getgrgid(myStat.st_gid);
        time_t t = myStat.st_mtime;
        localtime_r(&t, &lt);
        char timebuf[80];
        char timebuf2[80];

        strftime(timebuf, sizeof(timebuf), "%F", &lt);
        strftime(timebuf2, sizeof(timebuf2), "%R", &lt);
        printf( (S_ISDIR(myStat.st_mode)) ? "d" : "-");
        printf( (myStat.st_mode & S_IRUSR) ? "r" : "-");
        printf( (myStat.st_mode & S_IWUSR) ? "w" : "-");
        printf( (myStat.st_mode & S_IXUSR) ? "x" : "-");
        printf( (myStat.st_mode & S_IRGRP) ? "r" : "-");
        printf( (myStat.st_mode & S_IWGRP) ? "w" : "-");
        printf( (myStat.st_mode & S_IXGRP) ? "x" : "-");
        printf( (myStat.st_mode & S_IROTH) ? "r" : "-");
        printf( (myStat.st_mode & S_IWOTH) ? "w" : "-");
        printf( (myStat.st_mode & S_IXOTH) ? "x" : "-");
        printf(" ");
        printf("%ld ", myStat.st_nlink);
        if(pwd != 0){
            printf("%s %s %*ld %s %s %s\n", pwd->pw_name, gf->gr_name, len, (long)myStat.st_size, timebuf, timebuf2, myfile->d_name);
        }else  {

            printf("%d %s %*ld %s %s %s\n", myStat.st_uid, gf->gr_name, len, (long)myStat.st_size, timebuf, timebuf2, myfile->d_name);
            printf("\n");
        } 
        }
    closedir(mydir);
    }else{
        printf("ls: cannot open directory .: Permission denied");

    }


}

电流输出

total 8
-rw-rw-r-- 1 travis travis    0 2019-04-04 17:11 file2.txt
-rw-rw-r-- 1 travis travis    0 2019-04-04 17:11 file1.txt
drwxrwxr-x 4 travis travis 4096 2019-04-04 17:11 ..
drwxrwxr-x 2 travis travis 4096 2019-04-04 17:11 .
-rwxrwxrwx 1 travis travis    9 2019-04-04 17:11 link1
-rwxrwxrwx 1 travis travis    9 2019-04-04 17:11 link2

期望的输出

total 8
-rw-rw-r-- 1 travis travis    0 2019-04-04 17:11 file2.txt
-rw-rw-r-- 1 travis travis    0 2019-04-04 17:11 file1.txt
drwxrwxr-x 4 travis travis 4096 2019-04-04 17:11 ..
drwxrwxr-x 2 travis travis 4096 2019-04-04 17:11 .
lrwxrwxrwx 1 travis travis    9 2019-04-04 17:11 link1 -> file1.txt
lrwxrwxrwx 1 travis travis    9 2019-04-04 17:11 link2 -> file2.txt

【问题讨论】:

  • readlink是你要的功能,看我的回答
  • 您可能还想检查文件是否为符号链接:S_ISLNK
  • 所以如果 S_ISLNK 返回不为空,那么我如何附加以显示链接?您能否给我举个例子作为答案?
  • 我编辑了答案以添加提案

标签: c printing symlink ls


【解决方案1】:

在您的程序中,您查看st_nlink,但它涉及硬链接 (ln ...),而不是符号链接 (ln -s ...)

查看readlink你要写的路径

概要

  #include <unistd.h>

  ssize_t readlink(const char *pathname, char *buf, size_t bufsiz);

描述

  readlink()  places  the  contents  of the symbolic link pathname in the
  buffer buf, which has size bufsiz.  readlink() does not append  a  null
  byte  to buf.  It will (silently) truncate the contents (to a length of
  bufsiz characters), in case the buffer is too small to hold all of  the
   contents.

例如替换

   if(pwd != 0){
       printf("%s %s %*ld %s %s %s\n", pwd->pw_name, gf->gr_name, len, (long)myStat.st_size, timebuf, timebuf2, myfile->d_name);
   }else  {

       printf("%d %s %*ld %s %s %s\n", myStat.st_uid, gf->gr_name, len, (long)myStat.st_size, timebuf, timebuf2, myfile->d_name);
       printf("\n");
   } 

通过

    if(pwd != 0){
        printf("%s %s %*ld %s %s %s", pwd->pw_name, gf->gr_name, len, (long)myStat.st_size, timebuf, timebuf2, myfile->d_name);
    }else  {
        printf("%d %s %*ld %s %s %s", myStat.st_uid, gf->gr_name, len, (long)myStat.st_size, timebuf, timebuf2, myfile->d_name);
    } 

    char linkname[PATH_MAX];
    ssize_t r = readlink(myfile->d_name, linkname, PATH_MAX);

    if (r != -1) {
      linkname[r] = '\0';
      printf(" -> %s\n", linkname);
    }
    else
      putchar('\n');

【讨论】:

  • 好吧,现在尝试实施,以前从未使用过 readlink。如果我想将它插入到循环中,如果没有符号链接会导致错误吗?
  • @BretHasel 是你在非符号链接上使用它 readlink 将返回 -1 并且 errno 将设置为 EINVAL我>
  • 我可以请你举个例子吗?认为我用涉及 readlink 的 if 语句封装了我的打印语句,然后 if -1 打印我现在的状态,否则使用 readlink 打印。但是 readlink 是如何附加路径名的呢?
  • 谢谢你,我现在明白了很多,现在正在工作。
  • @BretHasel 很好,请注意,我没有在一个 printf("...", (pwd != 0) ? ... : ..., ...) 中更改您的 if(pwd != 0) printf(...); else printf(...) 以更好地显示更改,但只使用一个 printf 更简单;-)
猜你喜欢
  • 2013-01-12
  • 2013-11-10
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
  • 2013-02-12
  • 2015-10-30
  • 2013-02-19
  • 1970-01-01
相关资源
最近更新 更多