learn.lianglianglee.com/专栏/重学操作系统-完/06 目录结构和文件管理指令:rm -rf 指令的作用是?.md.html
2022-08-14 03:40:33 +08:00

459 lines
37 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<!-- saved from url=(0046)https://kaiiiz.github.io/hexo-theme-book-demo/ -->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
<link rel="icon" href="/static/favicon.png">
<title>06 目录结构和文件管理指令rm -rf 指令的作用是?.md.html</title>
<!-- Spectre.css framework -->
<link rel="stylesheet" href="/static/index.css">
<!-- theme css & js -->
<meta name="generator" content="Hexo 4.2.0">
</head>
<body>
<div class="book-container">
<div class="book-sidebar">
<div class="book-brand">
<a href="/">
<img src="/static/favicon.png">
<span>技术文章摘抄</span>
</a>
</div>
<div class="book-menu uncollapsible">
<ul class="uncollapsible">
<li><a href="/" class="current-tab">首页</a></li>
</ul>
<ul class="uncollapsible">
<li><a href="../">上一级</a></li>
</ul>
<ul class="uncollapsible">
<li>
<a href="/专栏/重学操作系统-完/00 开篇词 为什么大厂面试必考操作系统?.md.html">00 开篇词 为什么大厂面试必考操作系统?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/00 课前必读 构建知识体系,可以这样做!.md.html">00 课前必读 构建知识体系,可以这样做!</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/01 计算机是什么:“如何把程序写好”这个问题是可计算的吗?.md.html">01 计算机是什么:“如何把程序写好”这个问题是可计算的吗?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/02 程序的执行:相比 32 位64 位的优势是什么?(上).md.html">02 程序的执行:相比 32 位64 位的优势是什么?(上)</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/03 程序的执行:相比 32 位64 位的优势是什么?(下).md.html">03 程序的执行:相比 32 位64 位的优势是什么?(下)</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/04 构造复杂的程序:将一个递归函数转成非递归函数的通用方法.md.html">04 构造复杂的程序:将一个递归函数转成非递归函数的通用方法</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/05 存储器分级L1 Cache 比内存和 SSD 快多少倍?.md.html">05 存储器分级L1 Cache 比内存和 SSD 快多少倍?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/05 (1) 加餐 练习题详解(一).md.html">05 (1) 加餐 练习题详解(一)</a>
</li>
<li>
<a class="current-tab" href="/专栏/重学操作系统-完/06 目录结构和文件管理指令rm -rf 指令的作用是?.md.html">06 目录结构和文件管理指令rm -rf 指令的作用是?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/07 进程、重定向和管道指令xargs 指令的作用是?.md.html">07 进程、重定向和管道指令xargs 指令的作用是?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/08 用户和权限管理指令: 请简述 Linux 权限划分的原则?.md.html">08 用户和权限管理指令: 请简述 Linux 权限划分的原则?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/09 Linux 中的网络指令:如何查看一个域名有哪些 NS 记录?.md.html">09 Linux 中的网络指令:如何查看一个域名有哪些 NS 记录?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/10 软件的安装: 编译安装和包管理器安装有什么优势和劣势?.md.html">10 软件的安装: 编译安装和包管理器安装有什么优势和劣势?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/11 高级技巧之日志分析:利用 Linux 指令分析 Web 日志.md.html">11 高级技巧之日志分析:利用 Linux 指令分析 Web 日志</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/12 高级技巧之集群部署:利用 Linux 指令同时在多台机器部署程序.md.html">12 高级技巧之集群部署:利用 Linux 指令同时在多台机器部署程序</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/12 (1)加餐 练习题详解(二).md.html">12 (1)加餐 练习题详解(二)</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/13 操作系统内核Linux 内核和 Windows 内核有什么区别?.md.html">13 操作系统内核Linux 内核和 Windows 内核有什么区别?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/14 用户态和内核态:用户态线程和内核态线程有什么区别?.md.html">14 用户态和内核态:用户态线程和内核态线程有什么区别?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/15 中断和中断向量Javajs 等语言为什么可以捕获到键盘输入?.md.html">15 中断和中断向量Javajs 等语言为什么可以捕获到键盘输入?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/16 WinMacUnixLinux 的区别和联系:为什么 Debian 漏洞排名第一还这么多人用?.md.html">16 WinMacUnixLinux 的区别和联系:为什么 Debian 漏洞排名第一还这么多人用?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/16 (1)加餐 练习题详解(三).md.html">16 (1)加餐 练习题详解(三)</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/17 进程和线程:进程的开销比线程大在了哪里?.md.html">17 进程和线程:进程的开销比线程大在了哪里?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/18 锁、信号量和分布式锁:如何控制同一时间只有 2 个线程运行?.md.html">18 锁、信号量和分布式锁:如何控制同一时间只有 2 个线程运行?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/19 乐观锁、区块链:除了上锁还有哪些并发控制方法?.md.html">19 乐观锁、区块链:除了上锁还有哪些并发控制方法?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/20 线程的调度:线程调度都有哪些方法?.md.html">20 线程的调度:线程调度都有哪些方法?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/21 哲学家就餐问题:什么情况下会触发饥饿和死锁?.md.html">21 哲学家就餐问题:什么情况下会触发饥饿和死锁?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/22 进程间通信: 进程间通信都有哪些方法?.md.html">22 进程间通信: 进程间通信都有哪些方法?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/23 分析服务的特性:我的服务应该开多少个进程、多少个线程?.md.html">23 分析服务的特性:我的服务应该开多少个进程、多少个线程?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/23 (1)加餐 练习题详解(四).md.html">23 (1)加餐 练习题详解(四)</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/24 虚拟内存 :一个程序最多能使用多少内存?.md.html">24 虚拟内存 :一个程序最多能使用多少内存?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/25 内存管理单元: 什么情况下使用大内存分页?.md.html">25 内存管理单元: 什么情况下使用大内存分页?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/26 缓存置换算法: LRU 用什么数据结构实现更合理?.md.html">26 缓存置换算法: LRU 用什么数据结构实现更合理?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/27 内存回收上篇:如何解决内存的循环引用问题?.md.html">27 内存回收上篇:如何解决内存的循环引用问题?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/28 内存回收下篇:三色标记-清除算法是怎么回事?.md.html">28 内存回收下篇:三色标记-清除算法是怎么回事?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/28 (1)加餐 练习题详解(五).md.html">28 (1)加餐 练习题详解(五)</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/29 Linux 下的各个目录有什么作用?.md.html">29 Linux 下的各个目录有什么作用?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/30 文件系统的底层实现FAT、NTFS 和 Ext3 有什么区别?.md.html">30 文件系统的底层实现FAT、NTFS 和 Ext3 有什么区别?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/31 数据库文件系统实例MySQL 中 B 树和 B+ 树有什么区别?.md.html">31 数据库文件系统实例MySQL 中 B 树和 B+ 树有什么区别?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/32 HDFS 介绍:分布式文件系统是怎么回事?.md.html">32 HDFS 介绍:分布式文件系统是怎么回事?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/32 (1)加餐 练习题详解(六).md.html">32 (1)加餐 练习题详解(六)</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/33 互联网协议群TCPIP多路复用是怎么回事.md.html">33 互联网协议群TCPIP多路复用是怎么回事</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/34 UDP 协议UDP 和 TCP 相比快在哪里?.md.html">34 UDP 协议UDP 和 TCP 相比快在哪里?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/35 Linux 的 IO 模式selectpollepoll 有什么区别?.md.html">35 Linux 的 IO 模式selectpollepoll 有什么区别?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/36 公私钥体系和网络安全:什么是中间人攻击?.md.html">36 公私钥体系和网络安全:什么是中间人攻击?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/36 (1)加餐 练习题详解(七).md.html">36 (1)加餐 练习题详解(七)</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/37 虚拟化技术介绍VMware 和 Docker 的区别?.md.html">37 虚拟化技术介绍VMware 和 Docker 的区别?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/38 容器编排技术:如何利用 K8s 和 Docker Swarm 管理微服务?.md.html">38 容器编排技术:如何利用 K8s 和 Docker Swarm 管理微服务?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/39 Linux 架构优秀在哪里.md.html">39 Linux 架构优秀在哪里</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/40 商业操作系统:电商操作系统是不是一个噱头?.md.html">40 商业操作系统:电商操作系统是不是一个噱头?</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/40 (1)加餐 练习题详解(八).md.html">40 (1)加餐 练习题详解(八)</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/41 结束语 论程序员的发展——信仰、选择和博弈.md.html">41 结束语 论程序员的发展——信仰、选择和博弈</a>
</li>
</ul>
</div>
</div>
<div class="sidebar-toggle" onclick="sidebar_toggle()" onmouseover="add_inner()" onmouseleave="remove_inner()">
<div class="sidebar-toggle-inner"></div>
</div>
<script>
function add_inner() {
let inner = document.querySelector('.sidebar-toggle-inner')
inner.classList.add('show')
}
function remove_inner() {
let inner = document.querySelector('.sidebar-toggle-inner')
inner.classList.remove('show')
}
function sidebar_toggle() {
let sidebar_toggle = document.querySelector('.sidebar-toggle')
let sidebar = document.querySelector('.book-sidebar')
let content = document.querySelector('.off-canvas-content')
if (sidebar_toggle.classList.contains('extend')) { // show
sidebar_toggle.classList.remove('extend')
sidebar.classList.remove('hide')
content.classList.remove('extend')
} else { // hide
sidebar_toggle.classList.add('extend')
sidebar.classList.add('hide')
content.classList.add('extend')
}
}
function open_sidebar() {
let sidebar = document.querySelector('.book-sidebar')
let overlay = document.querySelector('.off-canvas-overlay')
sidebar.classList.add('show')
overlay.classList.add('show')
}
function hide_canvas() {
let sidebar = document.querySelector('.book-sidebar')
let overlay = document.querySelector('.off-canvas-overlay')
sidebar.classList.remove('show')
overlay.classList.remove('show')
}
</script>
<div class="off-canvas-content">
<div class="columns">
<div class="column col-12 col-lg-12">
<div class="book-navbar">
<!-- For Responsive Layout -->
<header class="navbar">
<section class="navbar-section">
<a onclick="open_sidebar()">
<i class="icon icon-menu"></i>
</a>
</section>
</header>
</div>
<div class="book-content" style="max-width: 960px; margin: 0 auto;
overflow-x: auto;
overflow-y: hidden;">
<div class="book-post">
<p id="tip" align="center"></p>
<div><h1>06 目录结构和文件管理指令rm -rf 指令的作用是?</h1>
<p>通过模块一的学习,你应该掌握了计算机组成原理的重点知识,到了模块二,我们开始学习 Linux 指令,它是操作系统的前端,学好这部分内容一方面可以帮助你应对工作场景,另一方面可以让你在学习操作系统底层知识前,对 Linux 有一个大概的了解。</p>
<p><strong>接下来,我们依然通过一道常见的高频面试题,引出今天的主要内容。面试题如下:请你说说</strong><code>rm / -rf</code><strong>的作用</strong></p>
<p>相信 90% 的同学是知道这个指令的。这里先预警一下,你千万不要轻易在服务器上尝试。要想知道这条指令是做什么的,能够帮助我们解决哪些问题,那就请你认真学习今天的内容。在本课时的最后我会公布这道题目的分析过程和答案。</p>
<h3>什么是 Shell</h3>
<p>在我们学习 Linux 指令之前,先来说一下什么是 ShellShell 把我们输入的指令,传递给操作系统去执行,所以 Shell 是一个命令行的用户界面。</p>
<p>早期程序员没有图形界面用,就用 Shell。而且图形界面制作成本较高不能实现所有功能因此今天的程序员依然在用 Shell。</p>
<p>你平时还经常会看到一个词叫作bashBourne Again Shell它是用 Shell 组成的程序。这里的 Bourne 是一个人名Steve Bourne 是 bash 的发明者。</p>
<p>我们今天学习的所有指令,不是写死在操作系统中的,而是一个个程序。比如<code>rm</code>指令,你可以用<code>which</code>指令查看它所在的目录。如下图所示,你会发现<code>rm</code>指令在<code>/usr/bin/rm</code>目录中。</p>
<p><img src="assets/Ciqc1F9rD96AC0GrAAB1NDHyN48035.png" alt="Drawing 0.png" /></p>
<p>如上图所示,<code>ramroll</code>是我的英文名字ubuntu 是我这台机器的名字。我输入了<code>which rm</code>,然后获得了<code>/usr/bin/rm</code>的结果,最终执行这条指令的是操作系统,连接我和操作系统的程序就是 Shell。</p>
<p>Linux 对文件目录操作的指令就工作在 Shell 上,接下来我们讲讲文件目录操作指令。</p>
<h3>Linux 对文件目录的抽象</h3>
<p>Linux 对文件进行了一个树状的抽象。<code>/</code>代表根目录,每一节目录也用<code>/</code>分开,所以在上图所展示的<code>/usr/bin/rm</code>中,第一级目录是<code>/</code>根目录,第二级目录是<code>usr</code>目录,第三级是<code>bin</code>目录。最后的<code>rm</code>是一个文件。</p>
<h4>路径path</h4>
<p><code>/usr/bin/rm</code>称为可执行文件<code>rm</code>的路径。路径就是一个文件在文件系统中的地址。如果文件系统是树形结构,那么通常一个文件只有一个地址(路径)。</p>
<p><strong>目标文件的绝对路径Absolute path也叫作完全路径full path是从</strong><code>/</code><strong>开始,接下来每一层都是一级子目录,直到</strong>定位<strong>到目标文件为止。</strong></p>
<p>如上图所示的例子中,<code>/usr/bin/rm</code>就是一个绝对路径。</p>
<h4>工作目录</h4>
<p>为了方便你工作Shell 还抽象出了工作目录。当用户打开 Shell 的时候Shell 就会给用户安排一个工作目录。因此也就产生了相对路径。</p>
<p>相对路径Relative path是以工作目录为基点的路径。比如</p>
<ul>
<li>当用户在<code>/usr</code>目录下的时候,<code>rm</code>文件的相对路径就是<code>bin/rm</code></li>
<li>如果用户在<code>/usr/bin</code>目录下的时候,<code>rm</code>文件的路径就是<code>./rm</code>或者<code>rm</code>,这里用<code>.</code>代表当前目录;</li>
<li>如果用户在<code>/usr/bin/somedir</code>下,那么<code>rm</code>的相对路径就是<code>../rm</code>,这里用<code>..</code>代表上一级目录。</li>
</ul>
<p>我们使用<code>cd</code>change directory指令切换工作目录既可以用绝对路径也可以用相对路径。 这里我要强调几个注意事项:</p>
<ul>
<li>输入<code>cd</code>不带任何参数会切换到用户的家目录Linux 中通常是<code>/home/{用户名}</code>。以我自己为例,我的家目录是<code>/home/ramroll</code></li>
<li>输入<code>cd .</code>什么都不会发生,因为<code>.</code>代表当前目录;</li>
<li>输入<code>cd..</code>会回退一级目录,因为<code>..</code>代表上级目录。</li>
</ul>
<p>利用上面这 3 种能力,你就可以方便的构造相对路径了。</p>
<p>Linux提供了一个指令<code>pwd</code>Print Working Directory查看工作目录。下图是我输入<code>pwd</code>的结果。</p>
<p><img src="assets/Ciqc1F9rEAqAYNQMAACAjjKxZlw157.png" alt="Drawing 1.png" /></p>
<p>你可以看到我正在<code>/home/ramroll/Documents</code>目录下工作。</p>
<h4>几种常见的文件类型</h4>
<p>另一方面Linux 下的目录也是一种文件;但是文件也不只有目录和可执行文件两种。常见的文件类型有以下 7 种:</p>
<ol>
<li>普通文件(比如一个文本文件);</li>
<li>目录文件(目录也是一个特殊的文件,它用来存储文件清单,比如<code>/</code>也是一个文件);</li>
<li>可执行文件(上面的<code>rm</code>就是一个可执行文件);</li>
<li>管道文件(我们会在 07 课时讨论管道文件);</li>
<li>Socket 文件(我们会在模块七网络部分讨论 Socket 文件);</li>
<li>软链接文件(相当于指向另一个文件所在路径的符号);</li>
<li>硬链接文件(相当于指向另一个文件的指针,关于软硬链接我们将在模块六文件系统部分讨论)。</li>
</ol>
<p>你如果使用<code>ls -F</code>就可以看到当前目录下的文件和它的类型。比如下面这种图:</p>
<ol>
<li>* 结尾的是可执行文件;</li>
<li>= 结尾的是 Socket 文件;</li>
<li>@ 结尾的是软链接;</li>
<li>| 结尾的管道文件;</li>
<li>没有符号结尾的是普通文件;</li>
<li>/ 结尾的是目录。</li>
</ol>
<p><img src="assets/Ciqc1F9rECOAaC4iAAEqYXENnnI551.png" alt="Drawing 2.png" /></p>
<h4>设备文件</h4>
<p>Socket 是网络插座是客户端和服务器之间同步数据的接口。其实Linux 不只把 Socket 抽象成了文件,设备基本也都被抽象成了文件。因为设备需要不断和操作系统交换数据。而交换方式只有两种——读和写。所以设备是可以抽象成文件的,因为文件也支持这两种操作。</p>
<p>Linux 把所有的设备都抽象成了文件比如说打印机、USB、显卡等。这让整体的系统设计变得高度统一。</p>
<p>至此,我们了解了 Linux 对文件目录的抽象,接下来我们看看具体的增删改查指令。</p>
<h3>文件的增删改查</h3>
<h4>增加</h4>
<p>创建一个普通文件的方法有很多,最常见的有<code>touch</code>指令。比如下面我们创建了一个 a.txt 文件。</p>
<p><img src="assets/CgqCHl9rEC-Ae_lzAAA_P5LZwCo061.png" alt="Drawing 3.png" /></p>
<p><code>touch</code>指令本来是用来更改文件的时间戳的,但是如果文件不存在<code>touch</code>也会帮助创建一个空文件。</p>
<p>如果你拿到一个指令不知道该怎么用,比如<code>touch</code>,你可以用<code>man touch</code>去获得帮助。<code>man</code>意思是 manual就是说明书的意思这里指的是系统的手册。如果你不知道<code>man</code>是什么,也可以使用<code>man man</code>。下图是使用<code>man man</code>的结果:</p>
<p><img src="assets/Ciqc1F9rEDqAMZ0vAAXe1wrRPf0386.png" alt="Drawing 4.png" /></p>
<p>另外如果我们需要增加一个目录,就需要用到<code>mkdir</code>指令( make directory比如我们创建一个<code>hello</code>目录,如下图所示:</p>
<p><img src="assets/CgqCHl9rEEGAKH5HAABgveVKHzI705.png" alt="Drawing 5.png" /></p>
<h4>查看</h4>
<p>创建之后我们可以用<code>ls</code>指令看到这个文件,<code>ls</code>是 list 的缩写。下面是指令 'ls' 的执行结果。</p>
<p><img src="assets/Ciqc1F9rEF-AVHcKAABf8ABbQ0o651.png" alt="Drawing 6.png" /></p>
<p>我们看到在当前的目录下有一个<code>a.txt</code>文件,还有一个<code>hello</code>目录。如果你知道当前的工作目录,就可以使用<code>pwd</code>指令。</p>
<p>如果想看到<code>a.txt</code>更完善的信息,还可以使用<code>ls -l</code><code>-l</code><code>ls</code>指令的可选参数。下图是<code>ls -l</code>的结果,你可以看到<code>a.txt</code>更详细的描述。</p>
<p><img src="assets/CgqCHl9rEGqAA0XWAAEv83hemN0703.png" alt="Drawing 7.png" /></p>
<p>如上图所示,我们看到两个<code>ramroll</code>,它们是<code>a.txt</code>所属的用户和所属的用户分组,刚好重名了。<code>Sep 13</code>是日期。 中间有一个<code>0</code><code>a.txt</code>的文件大小,目前<code>a.txt</code>中还没有写入内容,因此大小是<code>0</code></p>
<p>另外虽然<code>hello</code>是空的目录,但是目录文件 Linux 上来就分配了<code>4096</code>字节的空间。这是因为目录内需要保存很多文件的描述信息。</p>
<h4>删除</h4>
<p>如果我们想要删除<code>a.txt</code>可以用<code>rm a.txt</code>;如我们要删除<code>hello</code>目录,可以用<code>rm hello</code><code>rm</code>是 remove 的缩写。</p>
<p><img src="assets/CgqCHl9rEHSAaCuvAACmYor8yvE702.png" alt="Drawing 8.png" /></p>
<p>但是当我们输入<code>rm hello</code>的时候,会提示<code>hello</code>是一个目录,不可以删除。因此我们需要增加一个可选项,比如<code>-r</code>即 recursive递归。目录是一个递归结构所以需要用递归删除。最后你会发现<code>rm hello -r</code>删除了<code>hello</code>目录。</p>
<p>接下来我们尝试在 hello 目录下新增一个文件,比如相对路径是<code>hello/world/os.txt</code>。需要先创建 hello/world 目录。这种情况会用到<code>mkdir</code><code>-p</code>参数,这个参数控制<code>mkdir</code>当发现目标目录的父级目录不存在的时候会递归的创建。以下是我们的执行结果:</p>
<p><img src="assets/Ciqc1F9rEJKAYE8qAAFVKf9hzs8021.png" alt="Drawing 9.png" /></p>
<h4>修改</h4>
<p>如果需要修改一个文件,可以使用<code>nano</code>或者<code>vi</code>编辑器。类似的工具还有很多,但是<code>nano</code><code>vi</code>一般是<code>linux</code>自带的。</p>
<p>这里我不展开讲解了,你可以自己去尝试。在尝试的过程中如果遇到什么问题,可以写在留言区,我会逐一为你解答。</p>
<h3>查阅文件内容</h3>
<p>在了解了文件的增删改查操作后下面我们来学习查阅文件内容。我们知道Linux 下查阅文件内容,可以根据不同场景选择不同的指令。</p>
<p>当文件较小时,比如一个配置文件,想要快速浏览这个文件,可以用<code>cat</code>指令。下面 cat 指令帮助我们快速查看<code>/etc/hosts</code>文件。<code>cat</code>指令将文件连接到标准输出流并打印到屏幕上。</p>
<p><img src="assets/CgqCHl9rEKSAetBpAAJKmXNMtek042.png" alt="Drawing 10.png" /></p>
<p>标准输出流Standard Output也是一种文件进程可以将要输出的内容写入标准输出流文件这样就可以在屏幕中打印。</p>
<p>如果用<code>cat</code>查看大文件,比如一个线上的日志文件,因为动辄有几个 G控制台打印出所有的内容就要非常久而且刷屏显示看不到东西。</p>
<p>而且如果在线上进行查看大文件的操作,会带来不必要的麻烦:</p>
<p>首先因为我们需要把文件拷贝到输入输出流,这需要花费很长时间,这个过程会占用机器资源;</p>
<p>其次,本身文件会读取到内存中,这时内存被大量占用,很危险,这可能导致其他应用内存不足。因此我们需要一些不用加载整个文件,就能查看文件内容的指令。</p>
<p><strong>more</strong></p>
<p><code>more</code>可以帮助我们读取文件,但不需要读取整个文件到内存中。本身<code>more</code>的定位是一个阅读过滤器,比如你在<code>more</code>里除了可以向下翻页,还可以输入一段文本进行搜索。</p>
<p><img src="assets/CgqCHl9rEK6ANctWAAvN_sMIYLA038.png" alt="Drawing 11.png" /></p>
<p>如上图所示,我在<code>more</code>查看一个 nginx 日志后,先输入一个<code>/</code>,然后输入<code>192.168</code>看到的结果。<code>more</code>帮我找到了<code>192.168</code>所在的位置,然后又帮我定位到了这个位置。整个过程 more 指令只读取我们需要的部分到内存中。</p>
<p><strong>less</strong></p>
<p><code>less</code>是一个和<code>more</code>功能差不多的工具,打开<code>man</code>能够看到<code>less</code>的介绍上写着自己是<code>more</code>的反义词opposite of more。这样你可以看出<code>linux</code>生态其实也是很自由的一个生态,在这里创造工具也可以按照自己的喜好写文档。<code>less</code>支持向上翻页,这个功能<code>more</code>是做不到的。所以现在<code>less</code>用得更多一些。</p>
<p><strong>head/tail</strong></p>
<p><code>head</code><code>tail</code>是一组,它们用来读取一个文件的头部 N 行或者尾部 N 行。比如一个线上的大日志文件,当线上出了 bug服务暂停的时候我们就可以用<code>tail -n 1000</code>去查看最后的 1000 行日志文件,寻找导致服务异常的原因。</p>
<p>另一个比较重要的用法是,如果你想看一个实时的<code>nginx</code>日志,可以使用<code>tail -f 文件名</code>,这样你会看到用户的请求不断进来。查一下<code>man</code>,你会发现<code>-f</code>是 follow 的意思,就是文件追加的内容会跟随输出到标准输出流。</p>
<p><strong>grep</strong></p>
<p>有时候你需要查看一个指定<code>ip</code>的nginx日志或者查看一段时间内的<code>nginx</code>日志。如果不想用<code>less</code><code>more</code>进入文件中去查看,就可以用<code>grep</code>命令。Linux 的文件命名风格都很短,所以也影响了很多人,比如之前我看到过一个大牛的程序,变量名从来不超过 5 个字母,而且都有意义。</p>
<p>grep 这个词,我们分成三段来看,是 g|re|p。</p>
<ul>
<li>g 就是 global全局</li>
<li>re 就是 regular expression正则表达式</li>
<li>p 就是 pattern模式。</li>
</ul>
<p>所以这个指令的作用是通过正则表达式全局搜索一个文件找到匹配的模式。我觉得这种命名真的很牛软件命名也是一个世纪难题grep这个名字不但发音不错而且很有含义又避免了名字过长方便记忆。</p>
<p>下面我们举两个例子看看 grep 的用法:</p>
<ul>
<li>例 1查找 ip 地址</li>
</ul>
<p>我们可以通过<code>grep</code>命令定位某个<code>ip</code>地址的用户都做了什么事情,如下图所示:</p>
<p><img src="assets/CgqCHl9rELqAbYi4AAfJLxM4xgw204.png" alt="Drawing 12.png" /></p>
<ul>
<li>例 2查找时间段的日志</li>
</ul>
<p>我们可以通过 grep 命令查找某个时间段内用户都做了什么事情。如下图所示,你可以看到在某个 5 分钟内所有用户的访问情况。</p>
<p><img src="assets/Ciqc1F9rEMGAQTTHAAYTLdI_HSA050.png" alt="Drawing 13.png" /></p>
<h3>查找文件</h3>
<p>用户经常还会有一种诉求,就是查找文件。</p>
<p>之前我们使用过一个<code>which</code>指令,这个指令可以查询一个指令文件所在的位置,比如<code>which grep</code>会,你会看到<code>grep</code>指令被安装的位置是<code>/usr/bin</code>。但是我们还需要一个更加通用的指令查找文件,也就是 find 指令。</p>
<p><strong>find</strong></p>
<p>find 指令帮助我们在文件系统中查找文件。 比如我们如果想要查找所有<code>.txt</code> 扩展名的文件,可以使用<code>find / -iname &quot;*.txt&quot;</code><code>-iname</code>这个参数是用来匹配查找的i 字母代表忽略大小写,这里也可以用<code>-name</code>替代。输入这条指令,你会看到不断查找文件,如下图所示:</p>
<p><img src="assets/CgqCHl9rEM2AD9SWAAdsfnMr8fw422.png" alt="Drawing 14.png" /></p>
<h3>总结</h3>
<p>这节课我们学习了很多指令,不知道你记住了多少?最后,我们再一起复习一下。</p>
<ul>
<li><code>pwd</code>指令查看工作目录。</li>
<li><code>cd</code>指令切换工作目录。</li>
<li><code>which</code>指令查找一个执行文件所在的路径。</li>
<li><code>ls</code>显示文件信息。</li>
<li><code>rm</code>删除文件。</li>
<li><code>touch</code>修改一个文件的时间戳,如果文件不存在会触发创建文件。</li>
<li><code>vi</code><code>nano</code>可以用来编辑文件。</li>
<li><code>cat</code>查看完成的文件适合小型文件。</li>
<li><code>more``less</code>查看一个文件但是只读取用户看到的内容到内存,因此消耗资源较少,适合在服务器上看日志。</li>
<li><code>head``tail</code>可以用来看文件的头和尾。</li>
<li><code>grep</code>指令搜索文件内容。</li>
<li><code>find</code>指令全局查找文件。</li>
</ul>
<p>在这里,我再强调一个指令,即<code>man</code>指令,它是所有指令的手册,所以你一定要多多运用,熟练掌握。另外,一个指令通常有非常多的参数,但都需要用<code>man</code>指令去仔细研究。</p>
<p><strong>那么通过这节课的学习,你现在可以来回答本节关联的面试题目:</strong><code>rm / -rf</code><strong>的作用是?</strong></p>
<p>老规矩,请你先在脑海里先思考你的答案,并把你的思考写在留言区,然后再来看我接下来的分析。</p>
<p><strong>【解析】</strong></p>
<ul>
<li><code>/</code>是文件系统根目录;</li>
<li><code>rm</code>是删除指令;</li>
<li><code>-r</code>是 recursive递归</li>
<li><code>-f</code>是 force强制遇到只读文件也不提示直接删除。</li>
</ul>
<p>所以<code>rm -rf /</code>就是删除整个文件系统上的所有文件,而且不用给用户提示。</p>
</div>
</div>
<div>
<div style="float: left">
<a href="/专栏/重学操作系统-完/05 (1) 加餐 练习题详解(一).md.html">上一页</a>
</div>
<div style="float: right">
<a href="/专栏/重学操作系统-完/07 进程、重定向和管道指令xargs 指令的作用是?.md.html">下一页</a>
</div>
</div>
</div>
</div>
</div>
</div>
<a class="off-canvas-overlay" onclick="hide_canvas()"></a>
</div>
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652eace1692a40cfa3763df669d7439c1639079717194" integrity="sha512-Gi7xpJR8tSkrpF7aordPZQlW2DLtzUlZcumS8dMQjwDHEnw9I7ZLyiOj/6tZStRBGtGgN6ceN6cMH8z7etPGlw==" data-cf-beacon='{"rayId":"70997d53c9183cfa","version":"2021.12.0","r":1,"token":"1f5d475227ce4f0089a7cff1ab17c0f5","si":100}' crossorigin="anonymous"></script>
</body>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NPSEEVD756"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'G-NPSEEVD756');
var path = window.location.pathname
var cookie = getCookie("lastPath");
console.log(path)
if (path.replace("/", "") === "") {
if (cookie.replace("/", "") !== "") {
console.log(cookie)
document.getElementById("tip").innerHTML = "<a href='" + cookie + "'>跳转到上次进度</a>"
}
} else {
setCookie("lastPath", path)
}
function setCookie(cname, cvalue) {
var d = new Date();
d.setTime(d.getTime() + (180 * 24 * 60 * 60 * 1000));
var expires = "expires=" + d.toGMTString();
document.cookie = cname + "=" + cvalue + "; " + expires + ";path = /";
}
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i].trim();
if (c.indexOf(name) === 0) return c.substring(name.length, c.length);
}
return "";
}
</script>
</html>