Linux stat函式獲取檔案屬性(檔案大小,建立時間等,判斷普通檔案或者目錄等)
(注意:
1.部分平臺不支援stat64,
2.獲取檔案大小的型別 off_t,
在linux中off_t型別預設是32位的long int(4個位元組),
檔案太大時可能會溢位。
建議gcc編譯時加上-D_FILE_OFFSET_BITS=64選項,
off_t將會是8個位元組的型別。
3.獲取檔案大小,很多人會想到C語言的ftell函式,但該函式
侷限性很大,特別是對於大檔案。)
(1)函式的定義
表標頭檔案: #include <sys/stat.h>
#include <unistd.h>
定義函式: int stat(const char *file_name, struct stat *buf);
函式說明: 通過檔名filename獲取檔案資訊,並儲存在buf所指的結構體stat中
返回值: 執行成功則返回0,失敗返回-1,錯誤程式碼存於errno
錯誤程式碼:
ENOENT 引數file_name指定的檔案不存在
ENOTDIR 路徑中的目錄存在但卻非真正的目錄
ELOOP 欲開啟的檔案有過多符號連線問題,上限為16符號連線
EFAULT 引數buf為無效指標,指向無法存在的記憶體空間
EACCESS 存取檔案時被拒絕
ENOMEM 核心記憶體不足
ENAMETOOLONG 引數file_name的路徑名稱太長
(2)stat結構體
struct stat {
dev_t st_dev; //檔案的裝置編號
ino_t st_ino; //節點
mode_t st_mode; //檔案的型別和存取的許可權
nlink_t st_nlink; //連到該檔案的硬連線數目,剛建立的檔案值為1
uid_t st_uid; //使用者ID
gid_t st_gid; //組ID
dev_t st_rdev; //(裝置型別)若此檔案為裝置檔案,則為其裝置編號
off_t st_size; //檔案位元組數(檔案大小)
unsigned long st_blksize; //塊大小(檔案系統的I/O緩衝區大小)
unsigned long st_blocks; //塊數
time_t st_atime; //最後一次訪問時間
time_t st_mtime; //最後一次修改時間
time_t st_ctime; //最後一次改變時間(指屬性)
};
先前所描述的st_mode則定義了下列數種情況:
S_IFMT 0170000 檔案型別的位遮罩
S_IFSOCK 0140000 scoket
S_IFLNK 0120000 符號連線
S_IFREG 0100000 一般檔案
S_IFBLK 0060000 區塊裝置
S_IFDIR 0040000 目錄
S_IFCHR 0020000 字元裝置
S_IFIFO 0010000 先進先出
S_ISUID 04000 檔案的(set user-id on execution)位
S_ISGID 02000 檔案的(set group-id on execution)位
S_ISVTX 01000 檔案的sticky位
S_IRUSR(S_IREAD) 00400
檔案所有者具可讀取許可權
S_IWUSR(S_IWRITE)00200
檔案所有者具可寫入許可權
S_IXUSR(S_IEXEC) 00100
檔案所有者具可執行許可權
S_IRGRP 00040
使用者組具可讀取許可權
S_IWGRP 00020
使用者組具可寫入許可權
S_IXGRP 00010
使用者組具可執行許可權
S_IROTH 00004
其他使用者具可讀取許可權
S_IWOTH 00002
其他使用者具可寫入許可權
S_IXOTH 00001
其他使用者具可執行許可權
上述的檔案型別在POSIX中定義了檢查這些型別的巨集定義:
S_ISLNK (st_mode) 判斷是否為符號連線
S_ISREG (st_mode) 是否為一般檔案
S_ISDIR (st_mode) 是否為目錄
S_ISCHR (st_mode) 是否為字元裝置檔案
S_ISBLK (s3e) 是否為先進先出
S_ISSOCK (st_mode) 是否為socket
若一目錄具有sticky位(S_ISVTX),則表示在此目錄下的檔案只能被該檔案所有者、此目錄所有者或root來刪除或改名。
使用stat函式最多的可能是ls-l命令,用其可以獲得有關一個檔案的所有資訊。
(3)其他相關函式
函式都是獲取檔案(普通檔案,目錄,管道,socket,字元,塊()的屬性。
函式原型
#include <sys/stat.h>
int stat(const char *restrict pathname, struct stat *restrict buf);
提供檔名字,獲取檔案對應屬性。
int fstat(int filedes, struct stat *buf);
通過檔案描述符獲取檔案對應的屬性。
int lstat(const char *restrict pathname, struct stat *restrict buf);
提供檔名字,獲取檔案屬性。
主要區別:
fstat(int fd,struct stat *)接收的已open的檔案描述符
lstat(char *filename,struct stat *)接收的路徑名 ,需要注意的是,也能能處理符號連結,但處理的是符號連結本身(自身)檔案。
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <dirent.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#if 1
typedef struct stat Stat_t;
#define StatFunc(x,y) stat(x,y)
#else
typedef struct stat64 Stat_t; //部分平臺不支援
#define StatFunc(x,y) stat64(x,y)
#endif
int func(void)
{
char *filename ="binxu.rmvb" ;
int nRet = 0;
Stat_t s;
time_t tTimeTmp = 0;
struct tm stuTimeTmp;
memset(&s, 0, sizeof(Stat_t));
nRet = StatFunc(filename, &s);
if (nRet)
{
printf("stat %s failed! error_code: %s", filename ,strerror(errno));
return -1;
}
printf("\n s.st_size=%d,s.st_ctime=%d,s.st_mtime=%d,s.st_atime=%d \n",
s.st_size,s.st_ctime,s.st_mtime,s.st_atime);
if(s.st_size >0 )
{
printf("\n size ========%0.3lf KB %0.3lf M %0.3lf G ======\n",
s.st_size/1024.0,s.st_size/1024.0/1024.0,s.st_size/1024.0/1024.0/1024.0);
}
memset(&stuTimeTmp,0,sizeof(struct tm));
tTimeTmp = (s.st_ctime);
//struct tm *gmtime_r(const time_t *timep, struct tm *result);
(void *)gmtime_r(&tTimeTmp,&stuTimeTmp);
printf("\n create time** %d-%d-%d %d:%d:%d **\n",
stuTimeTmp.tm_year + 1900,
stuTimeTmp.tm_mon + 1,
stuTimeTmp.tm_mday,
stuTimeTmp.tm_hour,
stuTimeTmp.tm_min,
stuTimeTmp.tm_sec );
return 0;
}
int main()
{
func();
}
stat獲取到的檔案屬性的時間值是UTC時間。
在windows下看檔案屬性,時間+8北京時區剛好。
(4)利用stat 的屬性判斷屬於是否屬於同一掛載目錄下的資料夾或者是否是同一裝置
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <dirent.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#if 1
typedef struct stat Stat_t;
#define StatFunc(x,y) stat(x,y)
#else
typedef struct stat64 Stat_t; //部分平臺不支援
#define StatFunc(x,y) stat64(x,y)
#endif
int func(char *pchFilename)
{
int nRet = 0;
Stat_t stuStat;
dev_t mountDevice;
if(NULL == pchFilename || 0 == strlen(pchFilename))
{
return -1;
}
memset(&stuStat, 0, sizeof(Stat_t));
nRet = StatFunc(pchFilename, &stuStat);
if (nRet)
{
printf("stat %s failed! error_code: %s", pchFilename ,strerror(errno));
return -1;
}
printf("\n\n**************filepath[%s]*************** ",pchFilename);
printf("\n (stuStat.st_mode & S_IFMT) == S_IFBLK result is %d ",(stuStat.st_mode & S_IFMT) == S_IFBLK);
if ((stuStat.st_mode & S_IFMT) == S_IFBLK)
{
mountDevice = stuStat.st_rdev; // //(裝置型別)若此檔案為裝置檔案,則為其裝置編號
}
else
{
mountDevice = stuStat.st_dev; //檔案的裝置編號
}
printf("\n st_rdev[%llu] st_dev[%llu] st_ino[%lu]\n", stuStat.st_rdev,stuStat.st_dev,stuStat.st_ino );
return 0;
}
int main()
{
func("/share/111/");
func("/share/111/222/");
func("/");
func("/dev/sda1");
func("/dev/sda2");
func("/dev/sda5");
}
屬於裝置的,如/dev/sda1,(stuStat.st_mode & S_IFMT) == S_IFBLK條件為真,此時比較是否為同一裝置,應該比較st_rdev屬性
屬於資料夾的,(stuStat.st_mode & S_IFMT) == S_IFBLK條件為假,判斷是否同一個掛載點時,應該比較st_dev屬性。
相關文章
- nodejs獲取檔案資訊,判斷是檔案或目錄NodeJS
- 關於檔案系統在建立目錄檔案和普通檔案時的區別
- 檔案時間屬性
- 獲取Linux系統中目錄檔案大小的方法Linux
- python判斷檔案是否存在等操作Python
- java判斷檔案是否存在並建立檔案Java
- Linux的檔案屬性和目錄配置Linux
- shell判斷檔案,目錄是否存在或者具有許可權【轉】
- Linux下修改檔案建立時間(修改檔案更改時間)Linux
- C語言判斷檔案存在和建立檔案C語言
- c++ 獲取檔案建立時間、修改時間、訪問時間、檔案內容長度C++
- js判斷上傳檔案大小JS
- 在Progress中獲取檔案屬性
- java 獲取資料夾大小、檔案大小、檔案個數Java
- 目錄與檔案屬性:編寫ls
- shell迴圈判斷某一目錄下所有檔案大小,並清空滿足條件檔案
- Linux - 判斷檔案/目錄是否存在/具有許可權Linux
- py目錄下獲取指定字尾檔案打包成zip檔案
- Python 獲取檔案建立、訪問、修改時間Python
- 檔案和目錄之stat族函式——APUE學習筆記(2)函式筆記
- PHP獲取檔案基本屬性的方法PHP
- Linux檔案屬性Linux
- RMAN恢復表空間,資料檔案,歸檔檔案,控制檔案等介紹
- ln 覆蓋普通檔案或目錄
- Linux檔案系統-目錄和檔案管理Linux
- 獲取上傳檔案的大小
- linux獲取最新檔案時間以及sshpass使用Linux
- cp: 無法建立普通檔案 : 檔案已存在
- 檔案屬性
- proc_create_data函式建立/proc/目錄下的檔案函式
- node實現檔案屬性批量修改(時間屬性)
- 【萬里征程——Windows App開發】檔案&資料——獲取檔案屬性WindowsAPP
- Linux 檔案與目錄Linux
- Linux — 檔案、目錄管理Linux
- 認識 Linux 檔案屬性及檔案配置(轉)Linux
- QT選擇目錄等常用檔案/資料夾操作QT
- Linux下批量刪除空檔案或者刪除指定大小的檔案Linux
- XMl 檔案屬性的讀取XML