Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3844698
  • 博文数量: 146
  • 博客积分: 3918
  • 博客等级: 少校
  • 技术积分: 8584
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-17 13:52
个人简介

个人微薄: weibo.com/manuscola

文章分类

全部博文(146)

文章存档

2016年(3)

2015年(2)

2014年(5)

2013年(42)

2012年(31)

2011年(58)

2010年(5)

分类: LINUX

2012-06-23 10:46:48

    LINUX下文件系统的类型有7种文件类型,APUE中讲到,通过调用stat,可以看出文件的类型存储在st_mode里面。 这其中文件类型分别是:
  1. S_ISREG 普通文件
  2. S_ISDIR 目录文件
  3. S_ISCHR 字符特殊文件
  4. S_ISBLK 块设备文件
  5. S_ISFIFO 管道文件
  6. S_ISLNK 符号链接文件
  7. S_ISSOCK 套接字文件
    首先建立一个普通文本文件,这个比较简单

  1.       echo xxx>testfile
    如何判断一个文件是否是普通文件呢,C语言中用stat这个函数,下面是伪代码没有经过测试,检测目录文件,符号链接文件,都是这个套路,下面就不多讲。

点击(此处)折叠或打开

  1. #include
  2. struct stat statbuf={0};
  3. if(stat(testfile,&statbuf)!=0)
  4. {
  5.   printf("stat failed\n");
  6.   return -1;
  7. }
  8. if(S_ISREG(statbuf.st_mode))
  9. {
  10.   printf("testfile is REGULAR file\n" );
  11. }
     SHELL 如何判断文件是否是普通文件 还是软链接,还是PIPE文件呢。这就是本文的重点部分。

    上图是从UNIX shell范例精解中截下来的。可以看到,shell有一组命令可以方便的检测文件是否存在,如果存在是哪种类型的文件,是否可以读写执行。下面我们写个shell脚本来熟悉这些文件系统相关的shell命令。
       
  1. [beanl@localhost fs_shell]$ echo xxx>testfile
  2. [beanl@localhost fs_shell]$ mkfifo fifo_test
  3. [beanl@localhost fs_shell]$ mkdir testdir
  4. [beanl@localhost fs_shell]$ ln testfile testfile_hdlink
  5. [beanl@localhost fs_shell]$ ln -s testfile testfile_sflink
  6. [beanl@localhost fs_shell]$ ll -ai
  7. total 24
  8. 26187022 drwxrwxr-x 3 beanl beanl 4096 Jun 23 12:33 .
  9. 26187016 drwxrwxr-x 4 beanl beanl 4096 Jun 23 10:59 ..
  10. 26187064 prw-rw-r-- 1 beanl beanl 0 Jun 23 12:32 fifo_test
  11. 26187065 drwxrwxr-x 2 beanl beanl 4096 Jun 23 12:33 testdir
  12. 26187063 -rw-rw-r-- 2 beanl beanl 4 Jun 23 12:32 testfile
  13. 26187063 -rw-rw-r-- 2 beanl beanl 4 Jun 23 12:32 testfile_hdlink
  14. 26187066 lrwxrwxrwx 1 beanl beanl 8 Jun 23 12:33 testfile_sflink -> testfile
  15. 26187073 -rwxrwxr-x 1 beanl beanl 939 Jun 23 12:08 test.sh

    我们看一下:
    fifo文件ll的时候首字母为p表示他是管道文件。
    dir文件ll的首字母为d表示为目录文件
    普通文件ll的首字母为-
    符号链接文件 ll的首字母为l表示他是个链接,同时它会将它指向的文件显示出来。

    硬链接和软链接的区别:
    首先,我故意将inode信息打印出来,我们看,我为testfile建立了一个硬链接testfile_hdlink,他们的inode是同一个,都是26187063,软链接则不同是另外一个inode,26187066。这表明testfile_hdlink 同testfile本质是同一个文件,只不过他们的名字不同罢了。我们可以testfile和testfile_hdname文件的内容打印出来看一下:
    

  1. [beanl@localhost fs_shell]$ cat testfile
  2. xxx
  3. [beanl@localhost fs_shell]$ cat testfile_hdlink
  4. xxx
  5. [beanl@localhost fs_shell]$ echo zzzz>testfile_hdlink
  6. [beanl@localhost fs_shell]$ cat testfile_hdlink
  7. zzzz
  8. [beanl@localhost fs_shell]$ cat testfile
  9. zzzz
  10. [beanl@localhost fs_shell]$
    testfile和testfile_hdlink原本就是一个文件,修改其中一个,另一个也能反映出来,因为文件的数据都存在同一个地方。这是硬链接。

    软链接则不同,软链接本质是个文本文件,它记录了他指向的目的文件的名字。
  1. [beanl@localhost fs_shell]$ ln -s /home/beanl/code/LINUX/fs_shell/testfile testfile_sflink_2

  1. [beanl@localhost fs_shell]$ ll
  2. total 16
  3. prw-rw-r-- 1 beanl beanl 0 Jun 23 12:32 fifo_test
  4. drwxrwxr-x 2 beanl beanl 4096 Jun 23 12:33 testdir
  5. -rw-rw-r-- 2 beanl beanl 5 Jun 23 12:44 testfile
  6. -rw-rw-r-- 2 beanl beanl 5 Jun 23 12:44 testfile_hdlink
  7. lrwxrwxrwx 1 beanl beanl 8 Jun 23 12:33 testfile_sflink -> testfile
  8. lrwxrwxrwx 1 beanl beanl 40 Jun 23 12:48 testfile_sflink_2 -> /home/beanl/code/LINUX/fs_shell/testfile
  9. -rwxrwxr-x 1 beanl beanl 939 Jun 23 12:08 test.sh
      我们看,testfile_sflink的大小是8,这是因为我们是通过
  1. [beanl@localhost fs_shell]$ ln -s testfile testfile_sflink
 建立起了软链接,他指向的文件名就叫testfile 八个字符。 而testfile_sflink_2是40个字符,那是因为通过

点击(此处)折叠或打开

  1. [beanl@localhost fs_shell]$ ln -s /home/beanl/code/LINUX/fs_shell/testfile testfile_sflink_2
建立起了软链接,而全路径/home/beanl/code/LINUX/fs_shell/testfile 正好是四十个字节。

    这就验证了我们的结论,软连接本质不过就是个文本文件,它记录了他指向的文件的路径。UNIX系统编程书中讲到了软链接和硬链接的本质,介绍的比较精彩。

    如何获得软链接指向的文件呢?C语言中有readlink函数,感兴趣的可以去APUE查看,Advance Linux Program给出了实例,有兴趣可以去读一下代码。 Shell也有这个命令,通过readlink命令,可以容易的读出,软链接指向的文件,注意readlink给出的标准全路径,并不是我们前面提到的文本文件记录的那些字节。

  1. [beanl@localhost fs_shell]$ readlink -f testfile_sflink
  2. /home/beanl/code/LINUX/fs_shell/testfile
    OK,最后给出一段shell代码,来获取文件相关的信息。

  1. #!/bin/sh

  2. if [ -e filenotexist ]
  3. then
  4.    echo "filenotexist existed"
  5. else
  6.    echo "filenotexist not existed"
  7. fi

  8. if [ -d testdir ]
  9. then
  10.     echo "testdir is a dir"
  11. fi

  12. if [ -f testfile ]
  13. then
  14.    echo "testfile is a regular file"
  15. else
  16.    echo "testfile is not a regular file"
  17. fi

  18. if [ -h testfile_sflink ]
  19. then
  20.    REAL_PATH=`readlink -f testfile_sflink`
  21.    echo "testfile_sflink is a soft link point to " $REAL_PATH
  22. else
  23.    echo "testfile_sflink is not a soft link"
  24. fi

  25. if [ -p fifo_test ]
  26. then
  27.     echo "fifo_test is a pipe file"
  28. else
  29.     echo "fifo_test is not a pipe file"
  30. fi

  31. if [ -b /dev/sdb1 ]
  32. then
  33.     echo "/dev/sdb1 is block device file"
  34. else
  35.     echo "/dev/sdb1 is not block device file"
  36. fi

  37. if [ -c /dev/sdb1 ]
  38. then
  39.     echo "/dev/sdb1 is charactor device file"
  40. else
  41.     echo "/dev/sdb1 is not charactor device file"
  42. fi

  43. if [ -c /dev/tty0 ]
  44. then
  45.    echo "/dev/tty0 is character device file"
  46. else
  47.    echo "/dev/tty0 is not character device file"
  48. fi
运行结果如下:

  1. [beanl@localhost fs_shell]$ ./test.sh
  2. filenotexist not existed
  3. testdir is a dir
  4. testfile is a regular file
  5. testfile_sflink is a soft link point to /home/beanl/code/LINUX/fs_shell/testfile
  6. fifo_test is a pipe file
  7. /dev/sdb1 is block device file
  8. /dev/sdb1 is not charactor device file
  9. /dev/tty0 is character device file
  10. [beanl@localhost fs_shell]$


 参考文献:
1 UNIX shell 范例精解
2 UNIX系统编程
3 Linux Advance Program

阅读(7445) | 评论(7) | 转发(6) |
给主人留下些什么吧!~~

Heartwork2012-07-17 16:36:44

因为soft link本身存储的内容是目标文件的字符串,所以我狠好奇内核时怎么将它和regular file区分开……

liujunwei12342012-07-09 22:02:46

mark下,第一次看到shell下的文件类型判断。