linux系統編程:自己動手寫一個ls命令

来源:https://www.cnblogs.com/ghostwu/archive/2018/01/09/8253623.html
-Advertisement-
Play Games

ls用於列舉目錄內容,要實現這個功能,毫無疑問,需要讀取目錄,涉及到兩個api: opendir:DIR *opendir(const char *name), 傳文件名,返回一個指針,指向目錄序列 readdir:struct dirent *readdir(DIR *dirp), 把opendi ...


ls用於列舉目錄內容,要實現這個功能,毫無疑問,需要讀取目錄,涉及到兩個api:

opendir:DIR *opendir(const char *name), 傳文件名,返回一個指針,指向目錄序列

readdir:struct dirent *readdir(DIR *dirp), 把opendir的返回值傳過來,   返回值為一個結構體

        struct dirent {
               ino_t          d_ino;       /* inode number */
               off_t          d_off;       /* not an offset; see NOTES */
               unsigned short d_reclen;    /* length of this record */
               unsigned char  d_type;      /* type of file; not supported
                                              by all filesystem types */
               char           d_name[256]; /* filename */
           };

有了這兩個api,就可以實現一個簡易的ls功能

 1 /*================================================================
 2 *   Copyright (C) 2018 . All rights reserved.
 3 *   
 4 *   文件名稱:myls.c
 5 *   創 建 者:ghostwu(吳華)
 6 *   創建日期:2018年01月09日
 7 *   描    述: ls命令
 8 *
 9 ================================================================*/
10 
11 #include <stdio.h>
12 #include <sys/types.h>
13 #include <dirent.h>
14 #include <stdlib.h>
15 
16 void do_ls( char [] );
17 
18 int main(int argc, char *argv[])
19 {
20     if( argc == 1 ) {
21         do_ls( "." );
22     }else {
23         while( --argc ) {
24             printf( "arg=%s\n", * ++argv );
25             do_ls( *argv );
26         }
27     }
28     return 0;
29 }
30 
31 void do_ls( char dir_entry[] ) {
32     DIR* pDir;
33     struct dirent* pCurDir;
34     if( ( pDir = opendir( dir_entry ) ) == NULL ){
35         perror( "read dir" );
36         exit( -1 );
37     }else {
38         while( ( pCurDir = readdir( pDir ) ) != NULL ) {
39             printf( "%s\n", pCurDir->d_name );
40         }
41     }
42 }
View Code

這個簡易的ls功能,列舉出了所有的文件( 包括隱藏的 ), 但是很多的信息不全,如: 許可權,用戶和組,修改時間,文件大小,鏈接數目等,stat這個api可以獲取文件的這些信息

stat:獲取文件狀態信息

原型:int stat(const char *pathname, struct stat *buf), 第一個參數:文件名, 第二個參數:保存文件狀態信息的結構體( man 2 stat 有結構體相關說明 )

1、獲取文件的大小

 1 /*================================================================
 2 *   Copyright (C) 2018 . All rights reserved.
 3 *   
 4 *   文件名稱:stat.c
 5 *   創 建 者:ghostwu(吳華)
 6 *   創建日期:2018年01月09日
 7 *   描    述:
 8 *
 9 ================================================================*/
10 
11 #include <stdio.h>
12 #include <sys/stat.h>
13 
14 #define FILENAME "/etc/passwd"
15 
16 int main(int argc, char *argv[])
17 {
18     struct stat filestat;
19     
20     if( -1 == stat( FILENAME, &filestat ) ) {
21         perror( "file stat" );
22         return -1;
23     }else {
24         printf( "the size of %s is %ld\n",FILENAME,  filestat.st_size );
25     }
26 
27     return 0;
28 }
View Code

2、讀取文件st_mode(許可權位), 用戶id, 組id, 修改時間,鏈接數目

 1 /*================================================================
 2 *   Copyright (C) 2018 . All rights reserved.
 3 *   
 4 *   文件名稱:stat2.c
 5 *   創 建 者:ghostwu(吳華)
 6 *   創建日期:2018年01月09日
 7 *   描    述:
 8 *
 9 ================================================================*/
10 
11 #include <stdio.h>
12 #include <sys/stat.h>
13 #include <string.h>
14 #include <time.h>
15 
16 void show_info( char *file, struct stat* statinfo );
17 void show_time( time_t filetime );
18 char* format_time( char* dsttime, const char* srctime );
19 
20 int main(int argc, char *argv[])
21 {
22     struct stat fileinfo;
23     if( argc > 1 ) {
24         /*調試信息
25         printf( "%s\n", argv[1] );
26         int res = stat( argv[1], &fileinfo );
27         printf( "%d\n", res );
28         */
29         if( stat( argv[1], &fileinfo ) != -1 ) {
30             show_info( argv[1], &fileinfo );
31         }
32     }else {
33         perror( "get args from terminal" );
34     }
35     
36     return 0;
37 }
38 
39 void show_info( char* file, struct stat* statinfo ){
40     printf( "%s文件信息如下:\n", file );
41     printf( "st_mode = %d\n", statinfo->st_mode );
42     printf( "links = %ld\n", statinfo->st_nlink );
43     printf( "uid = %d\n", statinfo->st_uid );
44     printf( "gid = %d\n", statinfo->st_gid );
45     printf( "file size = %ld\n", statinfo->st_size );
46     show_time( statinfo->st_mtime );
47 }
48 
49 void show_time( time_t filetime ) {
50     struct tm* ptm;
51     ptm = localtime( &filetime );
52 
53     int month = ptm->tm_mon + 1;
54     int day = ptm->tm_mday;
55     int hour = ptm->tm_hour;
56     int min = ptm->tm_min;
57 
58     char srchour[3] = "0";
59     char srcmin[3] = "0";
60     char dsthour[3] = "0";
61     char dstmin[3] = "0";
62     sprintf( srchour, "%d", hour );
63     sprintf( srcmin, "%d", min );
64     format_time( dsthour, srchour );
65     format_time( dstmin, srcmin );
66 
67     printf( "文件最後修改時間: %d月\t%d\t%s:%s\n", month, day, dsthour, dstmin );
68 }
69 
70 char* format_time( char* dsttime, const char* srctime ) {
71     if( strlen( srctime ) < 2 ) {
72         return strcat( dsttime, srctime );
73     }
74     return strcpy( dsttime, srctime );
75 }
View Code

3、許可權st_mode轉字元許可權位( 如: -rwxrwxrwx ), 用戶id和組id轉用戶名和組名稱,判斷文件類型

  1 /*================================================================
  2 *   Copyright (C) 2018 . All rights reserved.
  3 *   
  4 *   文件名稱:stat3.c
  5 *   創 建 者:ghostwu(吳華)
  6 *   創建日期:2018年01月09日
  7 *   描    述:文件類型與許可權位
  8 *
  9 ================================================================*/
 10 
 11 #include <stdio.h>
 12 #include <stdlib.h>
 13 #include <sys/stat.h>
 14 #include <string.h>
 15 #include <sys/types.h>
 16 #include <pwd.h>
 17 #include <grp.h>
 18 
 19 void do_ls( char* filename );
 20 void show_filetype( char* filename, int filemode );
 21 void show_filetype2( char* filename, int filemode );
 22 void mode_to_letters( int filemode, char str[] );
 23 //用戶id轉名稱
 24 char* uid_to_name( uid_t uid );
 25 //組id轉名稱
 26 char* gid_to_name( gid_t gid );
 27 
 28 int main(int argc, char *argv[])
 29 {
 30     if( argc < 2 ) {
 31         printf( "usage:%s file\n", argv[0] );
 32         return -1;
 33     }else {
 34         do_ls( argv[1] );
 35     }
 36     return 0;
 37 }
 38 
 39 char* uid_to_name( uid_t uid ){
 40     return getpwuid( uid )->pw_name;
 41 }
 42 
 43 char* gid_to_name( gid_t gid ){
 44     return getgrgid( gid )->gr_name;
 45 }
 46 
 47 void do_ls( char* filename ) {
 48     struct stat fileinfo;
 49     if( stat( filename, &fileinfo ) == -1 ) {
 50         printf( "%s open failure\n", filename );
 51         exit( -1 );
 52     }
 53     //printf( "st_mode = %d\n", fileinfo.st_mode );    
 54     show_filetype( filename, fileinfo.st_mode );
 55     show_filetype2( filename, fileinfo.st_mode );
 56     char file_permission[10];
 57     mode_to_letters( fileinfo.st_mode, file_permission );
 58     printf( "%s\n", file_permission  );
 59     printf( "用戶:%s\n", uid_to_name( fileinfo.st_uid ) );
 60     printf( "組:%s\n", gid_to_name( fileinfo.st_gid ) );
 61 }
 62 
 63 //掩碼判斷文件類型
 64 void show_filetype( char* filename, int filemode ){
 65     //用st_mode的值跟0170000這個掩碼相位與的結果 判斷文件類型
 66     if ( ( filemode & 0170000 ) == 0100000 ){
 67         printf( "%s是普通文件\n", filename );
 68     }else if( ( filemode & 0170000 ) == 0040000 ){ 
 69         printf( "%s是目錄\n", filename );
 70     }else if ( ( filemode & S_IFMT ) == S_IFLNK ){
 71         printf( "%s是符號鏈接\n", filename );
 72     }
 73 }
 74 
 75 //用巨集判斷文件類型
 76 void show_filetype2( char* filename, int filemode ){
 77     if( S_ISREG( filemode ) ) {
 78         printf( "%s是普通文件\n", filename );
 79     }else if( S_ISDIR( filemode ) ) {
 80         printf( "%s是目錄\n", filename );
 81     }else if( S_ISLNK( filemode ) ){
 82         printf( "%s是符號鏈接\n", filename );
 83     }
 84 }
 85 
 86 //數字解碼成字母許可權位
 87 void mode_to_letters( int filemode, char str[] ) {
 88     strcpy( str, "----------" );
 89     if( S_ISREG( filemode ) ) str[0] = '-';
 90     if( S_ISDIR( filemode ) ) str[0] = 'd';
 91     if( S_ISLNK( filemode ) ) str[0] = 'l';
 92 
 93     //用戶許可權位
 94     if( filemode & S_IRUSR ) str[1] = 'r';
 95     if( filemode & S_IWUSR ) str[2] = 'w';
 96     if( filemode & S_IXUSR ) str[3] = 'x';
 97 
 98     //組許可權位
 99     if( filemode & S_IRGRP ) str[4] = 'r';
100     if( filemode & S_IWGRP ) str[5] = 'w';
101     if( filemode & S_IXGRP ) str[6] = 'x';
102 
103     //其他組許可權位
104     if( filemode & S_IROTH ) str[7] = 'r';
105     if( filemode & S_IWOTH ) str[8] = 'w';
106     if( filemode & S_IXOTH ) str[9] = 'x';
107 }
View Code

綜合上面3個小實例,可以得到格式化比較好的ls命令版本:

  1 /*================================================================
  2 *   Copyright (C) 2018 . All rights reserved.
  3 *   
  4 *   文件名稱:myls2.c
  5 *   創 建 者:ghostwu(吳華)
  6 *   創建日期:2018年01月09日
  7 *   描    述:ls命令( version 1.2 )
  8 *
  9 ================================================================*/
 10 
 11 #include <stdio.h>
 12 #include <sys/types.h>
 13 #include <dirent.h>
 14 #include <stdlib.h>
 15 #include <sys/types.h>
 16 #include <sys/stat.h>
 17 #include <unistd.h>
 18 #include <string.h>
 19 #include <sys/types.h>
 20 #include <pwd.h>
 21 #include <grp.h>
 22 #include <time.h>
 23 
 24 void do_ls( char [] );
 25 void do_stat( char* filename );
 26 void show_list( char* filename, struct stat* statinfo );
 27 void mode_to_letters( mode_t filemode, char str[] );
 28 void show_time( time_t filetime );
 29 char* format_time( char* dsttime, const char* srctime );
 30 
 31 //用戶id轉名稱
 32 char* uid_to_name( uid_t uid );
 33 //組id轉名稱
 34 char* gid_to_name( gid_t gid );
 35 
 36 int main(int argc, char *argv[])
 37 {
 38     if( argc == 1 ) {
 39         do_ls( "." );
 40     }else {
 41         while( --argc ) {
 42             printf( "arg=%s\n", * ++argv );
 43             do_ls( *argv );
 44         }
 45     }
 46     return 0;
 47 }
 48 
 49 void do_ls( char dir_entry[] ) {
 50     DIR* pDir;
 51     struct dirent* pCurDir;
 52     if( ( pDir = opendir( dir_entry ) ) == NULL ){
 53         perror( "read dir" );
 54         exit( -1 );
 55     }else {
 56         while( ( pCurDir = readdir( pDir ) ) != NULL ) {
 57             do_stat( pCurDir->d_name );
 58         }
 59         closedir( pDir );
 60     }
 61 }
 62 
 63 //得到文件信息
 64 void do_stat( char* filename ){
 65     struct stat statinfo;
 66     if ( stat( filename, &statinfo ) == -1 ) {
 67         printf( "打開%s失敗\n", filename );
 68         exit( -1 );
 69     }else {
 70         show_list( filename, &statinfo );
 71     }
 72 }
 73 
 74 //顯示文件列表
 75 void show_list( char* filename, struct stat* statinfo ) {
 76     mode_t st_mode = statinfo->st_mode;
 77 
 78     char str[10];
 79     mode_to_letters( st_mode, str );
 80     printf( "%s\t", str );
 81 
 82     printf( "%ld\t", statinfo->st_nlink ); //符號鏈接
 83     printf( "%s\t\t", uid_to_name( statinfo->st_uid ) ); //用戶名
 84     printf( "%s\t", gid_to_name( statinfo->st_gid ) ); //組名
 85     printf( "%10ld", statinfo->st_size ); //文件大小
 86     show_time( statinfo->st_mtime ); //最後一次修改時間
 87     printf( "\t%s", filename );
 88 
 89     printf( "\n" );
 90 }
 91 
 92 char* uid_to_name( uid_t uid ){
 93     return getpwuid( uid )->pw_name;
 94 }
 95 
 96 char* gid_to_name( gid_t gid ){
 97     return getgrgid( gid )->gr_name;
 98 }
 99 
100 void mode_to_letters( mode_t filemode, char str[] ) {
101 
102     strcpy( str, "----------" );
103     if( S_ISREG( filemode ) ) str[0] = '-';
104     if( S_ISDIR( filemode ) ) str[0] = 'd';
105     if( S_ISLNK( filemode ) ) str[0] = 'l';
106 
107     //用戶許可權位
108     if( filemode & S_IRUSR ) str[1] = 'r';
109     if( filemode & S_IWUSR ) str[2] = 'w';
110     if( filemode & S_IXUSR ) str[3] = 'x';
111 
112     //組許可權位
113     if( filemode & S_IRGRP ) str[4] = 'r';
114     if( filemode & S_IWGRP ) str[5] = 'w';
115     if( filemode & S_IXGRP ) str[6] = 'x';
116 
117     //其他組許可權位
118     if( filemode & S_IROTH ) str[7] = 'r';
119     if( filemode & S_IWOTH ) str[8] = 'w';
120     if( filemode & S_IXOTH ) str[9] = 'x';
121 }
122 
123 void show_time( time_t filetime ) {
124     struct tm* ptm;
125     ptm = localtime( &filetime );
126 
127     int month = ptm->tm_mon + 1;
128     int day = ptm->tm_mday;
129     int hour = ptm->tm_hour;
130     int min = ptm->tm_min;
131 
132     char srchour[3] = "0";
133     char srcmin[3] = "0";
134     char dsthour[3] = "0";
135     char dstmin[3] = "0";
136     sprintf( srchour, "%d", hour );
137     sprintf( srcmin, "%d", min );
138     format_time( dsthour, srchour );
139     format_time( dstmin, srcmin );
140 
141     printf( "%4d月%4d%4s:%2s", month, day, dsthour, dstmin );
142 }
143 
144 char* format_time( char* dsttime, const char* srctime ) {
145     if( strlen( srctime ) < 2 ) {
146         return strcat( dsttime, srctime );
147     }
148     return strcpy( dsttime, srctime );
149 }
View Code

 

總結:

1)opendir和readdir的用法

2)結構體struct dirent的應用

3)stat的用法


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • using System; using System.Diagnostics; using System.Linq; using System.ServiceModel; using System.ServiceModel.Channels; using System.ServiceModel.De... ...
  • <configSections> <section name="log4net" type="System.Configuration.IgnoreSectionHandler"/> <!--<section name="log4net" type="log4net.Config.Log4NetCo ...
  • "大叔博客" LindDotNetCore基礎介紹 1. 運行環境 2. 配置文件 3. 服務的註冊 4. 配置文件的註冊 5. 服務的使用 6. 配置文件的使用 運行環境 vs2017+.netcore2.0,vs需要升級到最新包 配置文件 appsetting.json,我們提出了開發環境,測試 ...
  • using System; using System.ServiceModel; using System.ServiceModel.Channels; //註意:需要引用程式集 System.ServiceModel 併在管理員模式下運行 class Program { static void M... ...
  • 析構函數又稱終結器,用於析構類的實例。 定義 析構函數(destructor) 與構造函數相反,當對象結束其生命周期時(例如對象所在的函數已調用完畢),系統自動執行析構函數。析構函數往往用來做“清理善後” 的工作(例如在建立對象時用new開闢了一片記憶體空間,delete會自動調用析構函數後釋放記憶體) ...
  • 一般情況下我們在使用mac系統過程中下載一些文件、新建一些項目之後,這些文件都會預設是只讀狀態,這時我們只需要簡單的一句許可權設置命令就可以解決 但是我們在對 usr/bin 目錄下的文件進行操作的時候往往會出現這樣的錯誤(上一篇博客中關於git安裝進行軟連接就會遇到這樣的問題) 這是因為一些mac用 ...
  • 僅主機可以實現主機和虛擬機linux之間的互通,然後用securecrt。互傳文件之類 1虛擬機設置的網路適配器選擇僅主機模式,其餘不動。 2在主機的網路適配器設置中: 在 VMware Workstation的編輯--》虛擬網路編輯器中可以看到有三種模式, VMware Network Adapt ...
  • 近期為了學習資料庫的操作,準備在虛擬機中搭建環境以便操作(為什麼在虛擬機搭建學習環境?),系統剛裝好第一步就被阻止了。 總是會提示Could not connect to。原因是虛擬機沒有安裝ssh服務導致的。 那麼我們就來安裝ssh服務。 沒報錯就沒問題了。 查看ssh服務是否運行。 這個狀態就是 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...