pwd命令:打印当前的工作目录

我们都知道每个目录下面都有两个特殊的目录( . 和 .. ), .: 当前目录, ..: 上层目录,  每个目录都有一个i节点与之相关联

ghostwu@ubuntu:~$ ls -i
bak examples.desktop python
core Music shell_script
c_program note software
data php tags
Desktop php_study Templates
Documents Pictures unix
Downloads Public Videos

通过ls -i就可以显示每个文件和目录的inode值,比如下面我用ls -ia显示所有文件的inode

1,当工作在basic目录下面的时候,   当前目录basic( 也就是. )他的inode值为1573909,   ..: 1507

2,当把路径切换到python时候, .: 1507 刚好就跟basic的 .. 相等。后面依次类推

通过inode的关联就把目录的层级关系给找出来了,下一个问题:如何知道,已经到达根目录?

ghostwu@ubuntu:~/python/basic$ ls -ia
. person2.class.py test1.py
.. person3.class.py test2.py
func2.py person4.class.py test3.py
func3.py person.class.py test4.py
func.py superlist.class.py
ghostwu@ubuntu:~/python/basic$ cd ..
ghostwu@ubuntu:~/python$ ls -ia
. .. advance basic django
ghostwu@ubuntu:~/python$ cd ..
ghostwu@ubuntu:~$ ls -ia
. .mysql_history
.. .navicat64
.adobe note
.atom php
...

在根目录(/)下面的. 和 ..,他们的inode节点有个特点, 都是相等的,所以只要判断当前目录的inode等于上层目录的inode,就可以断定,到达根目录了

ghostwu@ubuntu:/$ ls -1ia
.
..
bin
boot
cdrom
dev
etc
home
...

1,第一个要解决的问题: 如果通过路径/文件名,得到对应的inode值,通过stat函数,获得文件/目录的struct stat结构体,文件信息都在这里保存,包括inode

 /*================================================================
* Copyright (C) 2018 . All rights reserved.
*
* 文件名称:pwd.c
* 创 建 者:ghostwu(吴华)
* 创建日期:2018年01月10日
* 描 述:pwd命令编写
*
================================================================*/ #include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h> //读取当前文件的i节点
ino_t get_inode( char* name ); int main(int argc, char *argv[])
{
printf( "当前目录.的inode=%ld\n", get_inode( "." ) );
printf( "上层目录..的inode=%ld\n", get_inode( ".." ) );
return ;
} ino_t get_inode( char* name ) {
struct stat statinfo;
if( - == stat( name, &statinfo ) ) {
printf( "文件%s打开失败\n", name );
exit( - );
}
return statinfo.st_ino;
}

2,完整的pwd源码

 /*================================================================
* Copyright (C) 2018 . All rights reserved.
*
* 文件名称:pwd.c
* 创 建 者:ghostwu(吴华)
* 创建日期:2018年01月10日
* 描 述:pwd命令编写
*
================================================================*/ #include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h> #ifndef BUFSIZE
#define BUFSIZE 100
#endif //读取当前文件的i节点
ino_t get_inode( char* name );
void printpathto( ino_t cur_node );
//根据当前inode节点,找到它对应的路径名称
void inode_to_name( ino_t cur_node, char* str, int bufsize ); int main(int argc, char *argv[])
{
//printf( "当前目录.的inode=%ld\n", get_inode( "." ) );
//printf( "上层目录..的inode=%ld\n", get_inode( ".." ) );
printpathto( get_inode( "." ) );
putchar( '\n' );
return ;
} void printpathto( ino_t cur_node ) { char dir_name[BUFSIZE];
ino_t my_node;
//如果当前节点不等于..,说明没有到达根目录
if( cur_node != get_inode( ".." ) ) {
//切换到上层目录, 当前目录(.)的名称在上层目录(..)
//所以找名称之前,先要切换到上层目录
chdir( ".." );
inode_to_name( cur_node, dir_name, BUFSIZE );
//chdir( ".." ); //不能放在这里,放在这里 找不到目录的名称
my_node = get_inode( "." );
printpathto( my_node );
printf( "/%s", dir_name );
}
} void inode_to_name( ino_t cur_node, char* str, int bufsize ) {
DIR* dir_entry;
struct dirent* pCurDir;
if( ( dir_entry = opendir( "." ) ) == NULL ) {
printf( "open cur directory error\n" );
exit( - );
}
//printf( "cur inode=%ld\n", cur_node );
while( ( pCurDir = readdir( dir_entry ) ) != NULL ) {
if( cur_node == pCurDir->d_ino ) {
//printf( "%s\n", pCurDir->d_name );
strncpy( str, pCurDir->d_name, bufsize );
str[bufsize-] = '\0';
closedir( dir_entry );
return;
}
}
} ino_t get_inode( char* name ) {
struct stat statinfo;
if( - == stat( name, &statinfo ) ) {
printf( "文件%s打开失败\n", name );
exit( - );
}
return statinfo.st_ino;
}

运行之后的效果:

ghostwu@ubuntu:~/c_program/linux_unix/chapter4$ ./pwd
/ghostwu/c_program/linux_unix/chapter4

还少了一层home,在home这层停止了

ghostwu@ubuntu:/home$ ls -ia
. .. ghostwu lost+found

home这层确实是 . 和 ..相等? 为什么会有这样的情况? 因为/home这个是一个分区,在linux中,每个分区都有独立的根目录结构,  /home就是这个分区的根节点,只不过被挂载到根分区( / )下面

总结:

1)linux文件分区与结构

2)目录和文件通过inode组成级联关系

linux系统编程:自己动手写一个pwd命令的更多相关文章

  1. Linux系统编程【2】——编写who命令

    学到的知识点 通过实现who命令,学到了: 1.使用man命令寻找相关信息 2.基于文件编程 3.体会到c库函数与系统调用的不同 4.加深对缓冲技术的理解 who命令的作用 who命令的使用 在控制终 ...

  2. linux系统编程综合练习-实现一个小型的shell程序(一)

    之前已经花了不少篇幅学习了linux系统编程的很多知识点:文件与io.进程.信号.管道,而零散的知识点,怎么能够综合的串接起来是学习的一个很重要的目的,当然最好的方式就是用所学的知识点做一个项目了,所 ...

  3. Linux系统编程【3.2】——ls命令优化版和ls -l实现

    前情提要 在笔者的上一篇博客Linux系统编程[3.1]--编写ls命令中,实现了初级版的ls命令,但是与原版ls命令相比,还存在着显示格式和无颜色标记的不同.经过笔者近两天的学习,基本解决了这两个问 ...

  4. linux系统编程:自己动手写一个cp命令

    cp命令的基本用法: cp 源文件 目标文件 如果目标文件不存在 就创建, 如果存在就覆盖 实现一个cp命令其实就是读写文件的操作: 对于源文件: 把内容全部读取到缓存中,用到的函数read 对于目标 ...

  5. linux系统编程综合练习-实现一个小型的shell程序(四)

    上节中已经对后台作业进行了简单处理,基本上要实现的功能已经完了,下面回过头来,对代码进行一个调整,把写得不好的地方梳理一下,给代码加入适当的注释,这种习惯其实是比较好了,由于在开发的时候时间都比较紧, ...

  6. linux系统编程综合练习-实现一个小型的shell程序(三)

    上节中已经实现了对普通命令的解析,包括输入重定向,输出重定向,管道,后台作业,这次就来执行已经解析好的命令,对应的函数为:execute_command(),首先对带有管道的命令进行执行: 比如:&q ...

  7. linux系统编程综合练习-实现一个小型的shell程序(二)

    上节minishell当中,已经初步实现了一个简单命令的解析,这节来继续对更加复杂命令进行解析,包含:输入重定向的解析.管道行的解析.输出重定向的解析以及是否有后台作业的解析,如下: 下面对其进行实现 ...

  8. Linux系统编程(14)——shell常用命令

    1. ls命令 ls命令是列出目录内容(ListDirectory Contents)的意思.运行它就是列出文件夹里的内容,可能是文件也可能是文件夹. "ls -l"命令已详情模式 ...

  9. Linux系统编程【1】——编写more命令

    背景介绍 笔者知识背景 笔者接触Linux快一年了.理论知识方面:学习了操作系统基础知识,了解进程调度.内存分配.文件管理.磁盘I/O这些基本的概念. 实操方面:会使用Linux简单命令,在嵌入式系统 ...

随机推荐

  1. “全栈2019”Java多线程第三十章:尝试获取锁tryLock()方法详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  2. java操作数据库的基本方法

    此次开发工具为eclipse,才有的数据库驱动是mysql-connector-java-5.1.8-bin.jar 第一步,在eclipse的工程目录中引用mysql驱动 驱动下载地址:https: ...

  3. _tkinter.TclError: image "pyimage1" doesn't exist 解决办法

    _tkinter.TclError: image "pyimage1" doesn't exist 解决办法 1 def logout(self): 2 login.LoginWi ...

  4. android 回调函数使用简介

    //1---定义回调函数 public interface GirdMenuStateListener { void onSuccess(); void onError(); } //2---使用的地 ...

  5. Xamarin Forms MVVM实现效果说明

    实体对象定义Model2  和Model均可 实现响应效果 public class BaseModel : INotifyPropertyChanged { private bool _select ...

  6. opencv2函数学习之threshold:实现图像阈值化

    在opencv2中,threshold函数可以进行阈值化操作. double threshold( const Mat& src, Mat& dst, double thresh,do ...

  7. C# 多线程九之Timer类

    1.简介 相信写过定时任务的小伙伴都知道这个类,非常的轻量级,而且FCL中大量的类使用了这个方法,比如CancellationTokenSource的CancelAfter就是用Timer去做的. 当 ...

  8. 【Canal源码分析】重要类图

    从Canal的整体架构中,我们可以看出,在Canal中,比较重要的一些领域有Parser.Sink.Store.MetaManager.CanalServer.CanalInstance.CanalC ...

  9. 使用GitHub Pages + Jekyll 建立博客

    https://pages.github.com/ http://jekyllbootstrap.com/usage/jekyll-quick-start.html Jekyll是一个静态网站生成器, ...

  10. 常见数据结构的Java实现

    单链表的Java实现 首先参考wiki上的单链表说明,单链表每个节点包含数据和指向链表中下一个节点的指针或引用.然后看代码 import java.lang.*; public class Singl ...