在本章中,我们将详细介绍 Linux 中的文件。您将了解纯文本文件和二进制文件之间的区别,这是您将处理的两种最常见的文件内容类型。我们将向您展示这些文件如何在 Linux 中被布局和组织进文件系统“树”,然后深入到您需要的实用命令,以创建、修改、移动和编辑文件。然后,我们将以对命令行文本编辑器的实用介绍来完成我们对基础知识的介绍。
然而,在本章中,我们不仅仅停留在基础知识上。Linux 文件是值得(有时是字面上的)深入挖掘一些高级知识的一个主题。毕竟,“处理文件”是您作为开发者在 Linux 上要做的主要事情之一:编写和读取源代码和配置文件、搜索特定文件内容、复制和移动日志文件等。您在这些基础上的效率越高,您就会成为一个更全面的开发者,不必一遍又一遍地搜索基本的 Linux 命令,或在与同事进行故障排除的 Zoom 通话中尴尬地卡在命令行文本编辑器中。
首先,我们将讨论在文件系统树中搜索文件以及在单个文件中查找特定内容或模式。然后,我们将讨论您可能会遇到的特殊文件和替代文件系统,以及您需要知道的内容,以便有效地使用它们。

最后,您将了解到:
您可能遇到的多种文件类型及其用途您需要处理的最重要的文件数据类型Linux 文件系统以及您将用于处理它的命令文件编辑基础一些常见问题及避免方法本章内容很多,它是 Linux 技能的最重要基础之一。在继续之前确保您理解了每个部分——您不必在第一次阅读时记住一切,但尝试在阅读本章时,尽可能在自己的 Linux 环境中获得实践经验。当您在解决现实世界问题或面试工作时,了解这些知识会有实实在在的回报。
Linux 上的文件:绝对基础 为了分解 Linux 上的文件这个较大的主题,让我们先介绍一些您可能已经有所了解的绝对基础知识:纯文本文件和二进制文件。我们还将介绍一个实际的错误,您可能会在将 Windows 文件移动到 Unix 系统,或反之时看到。
纯文本文件 您将遇到的最简单的文本文件形式之一是强大的纯文本文件。虽然历史上它们是 ASCII 文件,但它们现在通常是 UTF-8 编码的。您可能会遇到其他文件编码,但这是罕见的,因为它们通常被认为是过时的。
什么是二进制文件? Unix 不像许多其他操作系统那样区分二进制文件和文本文件。所有文件都可以通过管道流式传输、编辑和追加。文件就是文件。当一个文件被设置为可执行时,Unix 将尽其所能执行它,无论是在 ELF(可执行和可链接格式,可能是今天最广泛使用的可执行格式)的情况下成功,还是在尝试执行图像或音频文件时失败。
这个简单的机制开启了一些惊人的可能性。例如,可执行文件可以通过压缩工具传输,然后通过一个网络隧道(如 SSH),在被解压缩并重新写入文件之前——所有这些都在一个命令中完成,没有任何临时文件。
然而,这也意味着,您应该小心避免创建这样的情况,即随机文件,例如由网站用户(包括日志文件!
)上传或修改的文件,有可能被执行。这可能导致严重的安全问题。
行结束符 虽然 Unix 文件,特别是文本文件,与其他操作系统上的文件类似,但值得一提的是,Windows(和 DOS)等在使用不同的行结束字符,这可能会在许多使用这些文本文件的程序中产生错误。尽管这只是在一种类型的系统上创建的文件然后复制到另一种系统时才会出现的情况(例如,将文件从 Linux 移动到 DOS),但了解一下是值得的。
不同行结束符的原因是历史性的,许多工具(例如 Git 和各种文本编辑器)将自动为您处理这种差异。然而,在极少数情况下,您可能需要手动转换文件。有著名的命令如 dos2unix 可以做到这一点,但这些在大多数类 Unix 操作系统上都必须手动安装。
然而,有一些方法可以使用更传统的实用程序来转换它们。
使用 sed:sed 's/^M$//' original_dos_file > unix_file 使用 tr:tr -d '\r' < original_dos_file > unix_file 就地使用 perl:perl -pi -e 's/\r\n/\n/g' original_file
现在我们已经讨论了您需要了解的关键基本概念,以便理解类 Unix 系统中的文件,让我们谈谈所有这些文件实际存在其中的上下文:Linux 文件系统。
文件系统树 文件系统层次结构标准(FHS)描述了类 Unix 系统的常规目录布局。Linux 遵循这个标准,本质上使其成为“Linux 的官方文件夹结构”。FHS 是一个标准化的树状结构,每个文件和目录都从根(一个简单地名为“/”的目录)开始。这个层次结构至关重要:尽管最终用户有地方可以随意使用自己的目录结构,但 /(根目录)内的每个子目录都有特定的目的。
这个文件系统层次结构的基本布局不需要很长时间就能学会,现在投入几分钟,您将对事物的存放位置有一种直觉——无论是应用程序二进制文件、日志、数据文件还是您的代码需要访问的外部设备。换句话说,它既简化了开发又简化了故障排除:当您知道事物应该在哪里时,在事件期间,您花费的时间就少了,不会感到困惑和不确定在哪里查找。此外,当涉及到编写自己的脚本和执行高级开发者预期的轻度系统管理任务时,这些知识是必需的。
以下是您经常引用或自己使用的一些重要文件系统位置:
/etc:系统和软件配置文件放在这里,组织成许多子目录。/bin 和 /sbin:系统二进制文件放在这里。不要乱动这些。/usr/bin 和 /usr/local/bin:您安装的软件和您自己的二进制文件放在这里,以便系统上的任何人都可以看到并执行它们。/var/log 和 /var/lib:/var 包含变量数据,这些是在系统运行时容易改变的事物,如应用程序日志(/var/log)和动态库(/var/lib),文件以及运行应用程序的其他状态。/var/lib/systemd:包含 systemd 配置的文件系统上的若干位置之一。/etc/systemd/system:自定义系统单元文件的好地方,如果您正在创建服务。/dev:用于表示硬件设备的专用文件系统。/proc:用于查询或更改系统状态的专用文件系统。基本文件系统操作 是时候深入到您作为开发者每天都会使用的 Unix 基础命令了。这套命令将允许您完成在任何系统上需要做的一系列基本命令行任务。一旦您学习并练习了本章中的命令,您将能够做到如下事情:
实时跟踪应用程序日志。修复损坏的配置文件以使应用程序工作。在本地 macOS 开发机器上的 Git 存储库中从一个目录移动到另一个目录。让我们从列出目录开始。确保您已登录到 Linux 或 Unix 系统(Ubuntu 或 macOS 都可以),并已打开终端应用程序,准备跟随操作。
ls 列出一个文件或目录。这个命令类似于图形用户界面中的“打开文件夹”。它列出了给定目录的内容。默认情况下,它使用当前目录:
/home/steve# lsmy_document.txt
在这个例子中,我的 shell 当前位置是 /home/steve 目录,其中包含一个文件(my_document.txt)。
不过,您可以通过将目录作为参数传递来要求 ls 列出系统上的任何目录路径:
/home/steve# ls /var/log/alternatives.log apt bootstrap.log btmp dpkg.log faillog lastlog wtmp
为了更有序的输出,您可能想要添加“-l”选项。这将给您一个“长列表”,这意味着每行一个文件或目录,以及额外的信息。
# ls -l /var/log/total 296-rw-r--r-- 1 root root 4686 Jun 24 02:31 alternatives.logdrwxr-xr-x 2 root root 4096 Jun 24 02:31 apt-rw-r--r-- 1 root root 64547 Jun 24 02:06 bootstrap.log-rw-rw---- 1 root utmp 0 Jun 24 02:06 btmp-rw-r--r-- 1 root root 177139 Jun 24 02:31 dpkg.log-rw-r--r-- 1 root root 32032 Oct 28 14:26 faillog-rw-rw-r-- 1 root utmp 296296 Oct 28 14:26 lastlog-rw-rw-r-- 1 root utmp 0 Jun 24 02:06 wtmp
简而言之,ls 命令是您在 Unix 文件系统上“四处看看”的方式。
pwd “print working directory”(打印工作目录)的缩写。这显示了您在文件系统上的位置,这是在当前 shell 会话的上下文中。如果我作为 steve 用户登录到 Linux 系统,并且我在我的主目录中,我可以期望看到 pwd 打印如下内容:
pwd/home/steve
cd 更改 shell 中当前的工作目录。使用此命令后运行的命令将从文件系统上新更改的位置的角度运行。
这里有一个示例目录:
Desktop├── anotherfile├── documents│ └── contract.txt├── somefile.txt└── stuff ├── nothing └── important
如果您在 Desktop 目录中,但随后使用 cd documents 更改为 documents 目录,那么在使用 ls 命令时,您将从这个新的角度获得不同的列表。让我们看看实际操作:
/home/steve/Desktop# lsanotherfile documents somefile.txt stuff/home/steve/Desktop# cd documents//home/steve/Desktop/documents# lscontract.txt
现在我们可以查看我们的周围环境(ls),在文件系统上移动(cd),并找出我们在哪里(pwd),让我们开始实际影响文件系统,通过创建和修改文件。
touch 这个操作写作 touch filepath。
根据您提供的 filepath 是否已经存在,touch 命令将执行以下两种操作之一:
如果路径上不存在文件,touch 将创建它:→ /tmp touch filepath → /tmp ls -l filepath -rw-r--r-- 1 dcohen wheel 0 Aug 7 16:02 filepath如果路径上已存在文件,touch 将更新该文件的访问和修改时间:→ /tmp touch filepath → /tmp ls -l filepath -rw-r--r-- 1 dcohen wheel 0 Aug 7 16:03 filepath注意,在长列表中唯一改变的是显示的修改时间。less less 是一个“分页器”——一个允许您一次查看一屏(一页)文件内容的程序:
less /etc/hosts
它是交互式的——一旦您使用它来查看文件,您可以:
使用鼠标滚轮或箭头键逐行上下滚动。使用空格键向下滚动一整页。用 /(输入您的搜索模式)RETURN 进行搜索。用 n 跳转到下一个匹配项。使用 q 退出程序。 花一两分钟练习使用它,您就会熟悉。tail tail 用于查看文件的最后几行:
tail /some/file
tail 的 -f(跟随)选项对于将日志实时流式传输到您的终端非常有用:
tail -f /var/log/some.log
使用 q 退出 tail。
mv mv(移动)用于移动和重命名文件。
移动 假设您有一个名为 somefile.txt 的文件:
→ Desktop ls -alh somefile.txt-rw-r--r-- 1 dcohen wheel 0B Aug 7 11:02 somefile.txt
假设您位于与文件相同的目录中,以下是如何将其移动到 /var/log 目录,而不重命名它:
mv somefile.txt /var/log/
重命名 现在您想将该文件重命名为 foobar:
mv /var/log/somefile /var/log/foobar
就是这样!
cp 要复制文件和目录,请使用 cp 命令:
cp file destination
复制名为 file 的文件到目标文件路径 destination。最常用的选项是 -r,或 --recursive;如果您正在复制一个目录,这将复制里面的所有内容。
cp -r /home/dave /storage/userbackups/
mkdir 使用以下命令创建一个名为 directoryname 的新空目录:
mkdir directoryname
一个有用的选项是 -p,它允许您在一条命令中创建嵌套目录。例如,如果您想创建一个包含名为 school 的目录的 Documents 目录,该目录又包含一个名为 reports 的目录,您可以运行以下命令:
mkdir -p Documents/school/reports
rm rm 删除(移除)文件和目录:
rm filename 删除名为 filename 的文件。rm -r directoryname 将删除名为 directoryname 的目录以及其中的每个文件和目录,递归地。 还有一个用于删除空目录的单独命令 rmdir,但它通常只在脚本中使用,开发者在其中谨慎地限制意外删除的影响范围。编辑文件 无论是更新配置文件、创建新的 Linux 服务,还是在故障排除期间做笔记,您在 Linux 上的工作偶尔需要在命令行上编辑文件。我们将在第 6 章,“命令行编辑文件”,中详细讨论命令行文件编辑,但这里将给出一个非常简短的概览。
如果您仅限于命令行环境,可能会使用以下一些 CLI 文本编辑器:
nano:几乎总是已安装或可用;易于使用vi:几乎到处都有安装;需要一些时间来适应vim:到处都可以轻松安装;比 vi 更多功能如果这些编辑器没有安装,您可以通过包管理器安装它们。例如,如果您使用的是 Ubuntu Linux,可以使用类似 sudo apt-get install nano(或将 nano 替换为 vim)的命令。我们将在第 9 章,“管理已安装的软件”,中更深入地探讨包管理命令。不管您选择哪种编辑器,都可以通过在命令行上简单地输入 [$EDITOR filename] 来编辑文件;例如:
vi filenamevim /some/filenano /another/file
如果文件存在,您将能够在编辑器中编辑它。 如果不存在,但目录存在,您将在第一次在编辑器中保存时在该路径创建一个新文件。 如果目录不存在,您可能能够编辑文件,但编辑器将无法在没有一些额外步骤的情况下将其写入文件系统。
在下一章,第 6 章,“命令行编辑文件”,中,我们将更深入地探讨 Linux 命令行文件编辑所涉及的实用技能。如果您在完成本章之前绝对需要编辑文件,只需输入 nano /path/to/the/file 并按照屏幕上的备忘单保存和退出。与此同时,让我们了解一下作为 Linux 开发人员您将遇到的各种文件类型。
文件类型 我们已经介绍了“常规”文件,例如纯文本文件或图像文件和可执行程序中的二进制数据。但是,您还需要知道如何在 Linux 中识别和使用其他几种类型的文件。无论您是在寻找刚刚插入机器的 USB 棒或键盘,创建指向文件的链接,还是检查 Web 进程已打开的网络套接字,您都想了解所有这些的一些信息。
以下是所有 Linux 文件类型及其用途:
常规文件:这是最常见的文件类型,包含文本或二进制数据。作为一名软件工程师,您几乎在每个编程任务中都会遇到常规文件,无论您是在编写代码、编辑配置文件还是执行程序。在长列表中,您可能会看到一个源代码文件的典型示例,如下所示:-rw-r--r-- 1 dave dave 210 Jan 04 09:30 main.c目录:目录是用于组织其他文件和目录的特殊文件。如果您曾经使用过 Windows 或 macOS(在那里它们被称为“文件夹”),那么您已经熟悉目录;它们包含其他文件和目录。在长列表中,像 /etc 这样的目录将显示为:drwxr-xr-x 5 root root 4096 Jan 04 09:21 /etc块特殊文件:这种特殊文件类型为硬件设备提供缓冲访问,这使它们特别适合像硬盘这样的设备,数据以大的、固定大小的块被访问。您很少会直接使用这些,除非在挂载文件系统时。一个示例可能是硬盘分区,显示为:brw-rw---- 1 root disk 8, 2 Jan 19 11:00 sda2这表示一个块设备,拥有者和组具有读写权限。字符特殊文件:与块文件类似,字符文件提供对硬件设备的非缓冲、原始访问,但它们是为数据不是以块为导向的设备设计的,如键盘或鼠标。您永远不会需要担心这些,尽管您在工作过程中偶尔可能会使用它们(例如,/dev/urandom,/dev/null 或 /dev/zero)。一个字符设备,如终端,在长列表中可能显示为:crw-rw-rw- 1 root tty 5, 1 Jan 19 22:00 /dev/tty1FIFO 特殊文件(“命名管道”):命名管道,不要与 shell 中经常使用的匿名管道混淆,用于进程间通信。您几乎永远不会需要处理这些,尽管您将使用它们的匿名表亲,在第 11 章,“管道和重定向”中,成为 Unix 高手。您不常遇到这些,但一个命名管道文件的示例,可能看起来像这样:prw-r--r-- 1 user user 0 Jan 21 10:00 mynamedpipe链接:链接是另一种类型的文件,作为对另一个文件的快捷方式。有两种类型的链接——硬链接和符号链接(软链接)。您几乎永远不会需要处理硬链接,但您可能会使用符号链接来创建方便的路径,以频繁访问的文件或确保多个路径指向同一个文件。我们将在下面更详细地介绍这些。一个符号链接可能显示为:lrwxrwxrwx 1 user user 7 Jan 21 10:30 versions/latest -> bin/app-3.1这个示例指示一个名为 latest 的链接指向名为 app-3.1 的文件。套接字:Unix 套接字用于 IPC(进程间通信),类似于管道文件。您可能会在排除需要相互通信的服务的故障时遇到套接字文件(“为什么 nginx 无法访问我的应用服务器?”)。一个套接字文件——在这个例子中,nginx 和 php-fpm 使用它来通信,以便运行 WordPress 应用——可能看起来像这样:srwxrwx--- 1 root socket 0 Jan 23 11:31 /run/wordpress.sock这个列表涵盖了您可能会遇到的额外的特殊文件类型,并给出了一些直觉,关于您如何在实际中(以及为什么)遇到它们。为了帮助您构建有用的实用技能,有一些特定类型我们需要更详细地探索。让我们从最常见的这些特殊文件类型开始,获得一些实际经验。
符号链接 符号链接,通常称为 symlinks 或软链接,是一种文件类型,作为对另一个文件或目录的引用。与硬链接不同,符号链接可以指向不同文件系统的文件或目录,并且它与其所引用的文件或目录保持独立的 inode。
您可以使用以下基本语法创建符号链接:
ln -s document.txt /path/to/create/link
ln(小写的 L)是“链接”命令。
例如,如果您在当前目录中有一个名为 file1.txt 的文件,并且您想创建一个名为 link1 的符号链接到它,您将使用命令:
ln -s file1.txt link1
现在,如果您使用 ls -l 对目录进行长列表显示,您将看到 link1 被列为指向 file1.txt 的链接:
ls -ltotal 0-rw-r--r-- 1 root root 0 Oct 28 16:08 file1.txtlrwxrwxrwx 1 root root 9 Oct 29 17:20 link1 -> file1.txt
当您访问 link1 时,例如,通过使用 cat link1 打印文件的内容,系统将自动解引用链接并给您 file1.txt 的内容。如果 file1.txt 被移动、删除或重命名,符号链接不会自动更新,并将指向一个不存在的文件(一个损坏的链接)。
符号链接特别适用于创建快捷方式、组织文件和目录,并维护灵活和逻辑的文件系统结构。
硬链接 硬链接是同一文件系统的现有文件的附加名称,有效地充当别名。原始文件和硬链接共享相同的 inode,这意味着对一个的更改会反映在另一个中。与符号链接不同,硬链接不能跨越文件系统边界或链接到目录。如果原始文件被删除,硬链接仍然会保留数据。要创建一个名为 link1 的硬链接到名为 file1.txt 的文件,您将使用命令:
ln file1.txt link1
file 命令 file 命令是一个实用程序,可以让您检查文件的类型。file 命令的基本用法很简单:输入 file 后跟文件名。例如:
file mysecret.txt
可能会输出 mysecret.txt: ASCII text,表明 mysecret.txt 是一个纯文本文件。
如果您有一个二进制文件,比如一个名为 mybinary 的编译程序,运行 file mybinary 可能会输出类似于 mybinary: ELF 64-bit LSB executable,表明该程序是一个二进制可执行文件。
对于一个目录,如 /home/user,运行 file /home/user 很可能会返回 /home/user: directory,表示 /home/user 是一个目录。
file 命令是一个快速了解您正在处理的文件类型的强大工具,特别是当处理未知或不熟悉的文件时。
如果您想探索,使用 file 命令检查以下文件:
file /bin/shfile /dev/zerofile /dev/urandomfile /dev/sda1file ~/.bashrcfile /bin/lsfile /homefile /proc/1/cwd
高级文件操作 当您在类 Unix 操作系统中使用文件时,
您经常会想要对它们、它们的内容或与它们一起执行操作,但不是直接在编辑器中修改它们。例如,您可能想要:
搜索文件以查看它是否包含您正在寻找的内容。确定一批在特定时间修改的文件。安全地将文件移动到另一个系统,而不是仅在本地机器上使用 mv 复制它。您甚至可能想要将所有这三个合并为一个单一的操作!
这种类型的知识在故障排除期间(在日志中搜索特定的请求 ID 或错误代码)、开发期间(查找最近修改的源代码文件)或您想要进行一些测试时(将更新的应用程序源代码复制到测试系统)确实非常有用。
以下是这些类型文件操作的快速预览,以给您一个概念,了解您将使用的工具和命令来完成它们。
使用 grep 搜索文件内容 文本匹配通常使用 grep 完成。在您的个人或工作笔记本电脑上,您可能想要安装 ag 或 rg,这是更友好、更快版本的 grep(例如,sudo apt-get install silversearcher-ag),但在生产系统上,您总是会有 grep。
在文件 path/to/file 中搜索模式 search_pattern:
grep "search_pattern" path/to/file
您当然可以像这样搜索字符串,但 grep 如此强大的原因是它允许您使用正则表达式(regexes)来搜索模式。以下命令将返回以 startswith 开头的行:
grep ^startswith /some/file
而这个命令将返回以 endswith 结尾的行:
grep endswith$ /some/file
正则表达式非常有用,每个开发人员和 Linux 用户都应该熟悉基础知识。
您也可以使用 grep 递归地搜索目录——即搜索它包含的所有目录中的所有文件:
root@c7f1417df8d2:/tmp# grep -r -i "hello world" /tmp/tmp/secret/dontlook.key:hello world/tmp/hi.txt:hello world/tmp/hi.txt:HeLlO WoRlD! You found me!
但是,如果您不想在文件中找到字符串——如果您想要找到特定的文件本身呢?
使用 find 查找文件 find 可以帮助您通过名称、修改时间或其他属性查找文件和目录。它本质上是文件系统树的广度优先搜索,这对于以下事项非常有用:
查找所有在最近一天创建或修改的应用日志文件。识别所有名称以 _test.go 结尾的源代码测试文件。定位所有由实习生程序员留下的 php.ini 文件,以便您可以删除它们。以下示例中,/search/path 是您想要搜索的文件系统部分。如果您想搜索当前目录及其所有子目录,可以使用点字符(.),例如,find . -name 'file.txt':
按扩展名查找文件:find /search/path -name '.ext'查找匹配多个路径/名称模式的文件:find /search/path -path '/path//.ext' -or -name 'pattern'在不区分大小写的模式下,查找匹配给定名称的目录:find /search/path -type d -iname 'lib'查找匹配给定模式的文件,排除特定路径:find /search/path -name '.py' -not -path '/site-packages/'查找匹配给定大小范围的文件:find /search/path -size +500k -size –10M使用 rsync 在本地和远程主机之间复制文件 rsync 是一个极其有用的工具,可以在主机之间和跨主机复制文件和目录。它的工作方式与 cp 相同,只不过它适用于一个或两个主机远程的情况。
rsync 本质上是 cp(用于复制数据)和 ssh(用于安全、加密传输)的组合。如果您不熟悉 ssh,您需要学习它如何工作(并设置自己的 SSH 密钥和访问权限),然后再尝试 rsync 命令。
以下是一些示例调用,感谢 tldr 项目:
将文件从本地传输到远程主机:rsync path/to/local_file remote_host:path/to/remote_directory将文件从远程主机传输到本地:rsync remote_host:path/to/remote_file path/to/local_directory以归档模式 ([a]rchive)(保留属性)和压缩 ([z]ipped) 模式与 [v]erbose 和 [h]uman-readable [P]rogress:rsync -azvhP path/to/local_directory remote_host:path/to/remote_directory最后一个示例是我用来快速、自动备份的示例之一。结合 find、grep 和 rsync 我们将在第 11 章,“管道和重定向”中详细查看使用 | 字符组合命令,但这里是一个快速预览。
例如,如果您想要结合您刚刚看到的例子,例如,备份所有在 /tmp 目录中在过去一周修改过且包含 "hello world" 的所有文件,那只是一个聪明的命令:
find /tmp -type f -mtime -7 -exec grep -l "hello world" {} \; | xargs -I _ backupscript.sh _ backup@backupserver.local:/backups_
首先,我们运行 find,寻找小于 7 天前修改时间的文件。我们使用 find 的 -exec 标志来执行一个 grep 命令,带有 -l 标志,这只返回匹配文件的文件名。然后,我们将这些文件名管道传输到 xargs 命令,它对它从上一个命令接收到的每一行输入应用一个动作。在这种情况下,动作是运行一个虚构的备份脚本,以及一个虚构的目标路径,有人可能想要备份这个文件。
如果我们有上面 grep 部分中相同的文件,这个看起来狂野的命令将为您运行两个命令:
backupscript.sh /tmp/secret/dontlook.key backup@backupserver.local:/backups/tmp/secret/dontlook.keybackupscript.sh /tmp/hi.txt backup@backupserver.local:/backups/tmp/hi.txt
它正在做我们想要的:仅在我们关心的包含 "hello world" 内容的两个文件上运行备份脚本,并且它们在过去 7 天内被修改过。
虽然像这样的命令可能确实需要几分钟(和一些搜索)来组合,但它可能会在长远中为您节省数小时。这就是命令行环境的力量,结合小的、专注的 Unix 工具,您可以根据需要以任何方式组合它们。
您将在第 11 章,“管道和重定向”中了解更多关于 Unix 管道和 xargs 的信息,但我们给出了这个示例,因为让您了解如何将所有这些简单的命令结合起来是很重要的,随着您学习它们。
现实世界的高级文件系统知识 您现在已经对各种 Linux 文件类型有了介绍,并且对最常用的类型有一些经验。现在让我们来看看一些不太常见的文件系统知识,这些知识在您在 Linux 系统上工作时会派上用场。
当您遇到这些情况时:
排除您的第一个 Docker 应用程序的故障,该应用程序挂载了存储卷。开发与工业控制器、摄像头或其他外部硬件通信的应用程序。编写需要访问随机性以安全生成密码或 API 令牌的应用程序代码。您会看到一些特殊文件类型,包括块设备,它们是类似于某种磁盘的设备,数据以块的形式获取和读取。
传统磁盘设备是块设备,您通常会发现它们附加在文件系统的这些位置:
/dev/hdX/dev/sdX/dev/nvmeN其中 X 和 N 是相应磁盘的字母或数字索引,如 /dev/sda 或 /dev/nvme0。分区看起来就像磁盘一样,但附加了一个额外的数字或字符,例如 /dev/sda0,是第一个驱动器上的第一个分区。
请注意,即使操作系统检测到一个新的硬盘并将其(和任何检测到的分区)附加到这些位置之一,您仍然必须有意地使用 mount 命令“挂载”驱动器上的文件系统。这不是开发人员特别常见的操作,所以我们就到这里。
还有特殊的“软件设备”。这些设备从 /dev/null 开始,您可能已经看到输出被管道到 somecommand > /dev/null 的形式,到 /dev/random 和 /dev/urandom,它们为您提供随机字节。这是您的编程语言最有可能从哪里检索其加密安全的随机数。
另一个目录是 /proc,这是一个由 Plan 9 操作系统推广的文件系统,但在 Unix 早期就已构想。顾名思义,它被创建为用文件表示进程。/proc 包含以进程 ID 命名的目录,其中包含可以用于读取这些进程状态的文件。特别是在 Linux 上,它已经通过各种其他接口进行了扩展,包括配置内核驱动程序的方式,读取硬件信息和传感器输出,甚至与 BIOS 和 UEFI 交互。
FUSE:Unix 文件系统的更多乐趣 正如您刚刚看到的,Unix 中的许多事物都可以被解释为文件。理念是编辑文件是常见的操作,因此能够与文件交互的命令和编程语言提供了一个易于理解的接口。FUSE,全称为 Filesystem in Userspace,是一个 API,它允许任何人实现新的 Unix 文件系统,而无需成为内核程序员。换句话说,因为许多事物都可以与文件对话,所以能够为那些不是您期望的典型本地存储数据的“假冒” Unix 文件 API 是很有用的。如果这听起来有点狂野,可以看看人们用 FUSE 实现的一些事物。FUSE 已被用来实现许多传统的文件系统驱动程序,例如 NTFS,这样您就可以在 Linux 机器上读取旧的 Windows 文件系统。然而,由于 FUSE 的灵活性和易用性,也有一些相当狂野的文件系统是通过这种方式实现的:
例如,sshfs 允许您本地挂载另一台通过 SSH 访问的机器上的目录。 其他 FUSE 文件系统允许您将远程云存储(如 Amazon 的 S3)挂载为本地目录。 一些更晦涩的实现了将 Wikipedia 挂载为文件目录,或将 IRC 协议和天气预报 API 等服务表示为文件系统。
FUSE 如此有用,以至于它已经进入了许多类 Unix 操作系统,甚至在 Windows 上也可用。了解它很有价值,不仅因为它是 Unix 文件抽象的一个新颖用法,而且当您处理存储在某个地方但没有任何经典 API 可以在应用程序层面使用的信息时,它可能极其有用。您可能使用的所有编程语言都有标准库,让您与 Unix 文件系统上的文件对话,而 FUSE 是为几乎所有类型的信息创建该接口的一种方式。
结论 本章是一段深入 Linux 文件和文件系统基础以及一些更高级部分的激烈旅程。您看到了纯文本文件和二进制文件之间的区别,探索了 Linux 文件系统树的布局,并学习了所有需要的基本命令来处理文件。如果您做得对,您还花了一些时间在自己的 Linux 环境中,练习了我们在这里向您展示的重要命令行文件编辑技能。
在涵盖了基础知识之后,我们进入了您将需要的最关键的中级和高级话题。您看到了如何查找文件和搜索它们的内容,我们还让您初步了解了特殊文件和文件系统。
所有这些综合起来,为您提供了使用 Linux 解决现实世界问题所需的最重要技能和知识。我们希望您在这次旋风之旅中玩得开心!