本章专门介绍文件操作。正如在一切都是文件系统中一样,文件操作被认为是使用 Linux 最重要的方面之一。我们将从探索常见的文件操作开始,例如创建、复制和删除文件。我们将继续讨论归档,这是处理命令行时的另一个重要工具。本章的最后一部分将致力于在文件系统上查找文件,这是 shell 脚本编写器工具集中的另一项重要技能。
本章将介绍以下命令:cp
、rm
、mv
、ln
、tar
、locate
和find
。
本章将涵盖以下主题:
- 常见文件操作
- 归档
- 查找文件
我们将使用我们在第 2 章、设置您的本地环境中创建的虚拟机来练习文件操作。目前不需要更多的资源。
到目前为止,我们主要介绍了与 Linux 文件系统上的导航相关的命令。在前面的章节中,我们已经看到可以分别使用mkdir
和touch
来创建目录和空文件。如果我们想给文件一些有意义的(文本)内容,我们使用vim
或nano
。然而,我们还没有谈到删除文件或目录,或复制,重命名,或创建快捷方式。让我们从复制文件开始。
本质上,在 Linux 上复制文件真的很简单:使用cp
命令,后面跟着要复制的文件名到要复制的文件名。它看起来像这样:
reader@ubuntu:~$ ls -l
total 12
-rw-rw-r-- 1 reader reader 69 Jul 14 13:18 nanofile.txt
drwxrwxr-x 2 reader reader 4096 Aug 4 16:16 testdir
-rwxr-xr-- 1 reader reader 0 Aug 4 13:44 testfile
drwxrwx--- 2 reader reader 4096 Aug 4 16:18 umaskdir
-rw-rw---- 1 reader games 0 Aug 4 16:18 umaskfile
reader@ubuntu:~$ cp testfile testfilecopy
reader@ubuntu:~$ ls -l
total 12
-rw-rw-r-- 1 reader reader 69 Jul 14 13:18 nanofile.txt
drwxrwxr-x 2 reader reader 4096 Aug 4 16:16 testdir
-rwxr-xr-- 1 reader reader 0 Aug 4 13:44 testfile
-rwxr-xr-- 1 reader reader 0 Aug 18 14:00 testfilecopy
drwxrwx--- 2 reader reader 4096 Aug 4 16:18 umaskdir
-rw-rw---- 1 reader games 0 Aug 4 16:18 umaskfile
reader@ubuntu:~$
如您所见,在本例中,我们复制了一个(空的)文件,该文件已经属于我们的*,而我们与该文件在同一个目录中。这可能会引发一些问题,例如:*
- 我们是否总是需要与源文件和目标文件在同一个目录中?
- 文件的权限呢?
- 我们还能用
cp
复制目录吗?
正如您所料,与 Linux 下的许多东西一样,cp
命令也非常通用。我们确实可以复制不属于我们的文件;我们不需要和文件在同一个目录中,我们也可以复制目录!让我们试着做一些这样的事情:
reader@ubuntu:~$ cd /var/log/
reader@ubuntu:/var/log$ ls -l
total 3688
<SNIPPED>
drwxr-xr-x 2 root root 4096 Apr 17 20:22 dist-upgrade
-rw-r--r-- 1 root root 550975 Aug 18 13:35 dpkg.log
-rw-r--r-- 1 root root 32160 Aug 11 10:15 faillog
<SNIPPED>
-rw------- 1 root root 64320 Aug 11 10:15 tallylog
<SNIPPED>
reader@ubuntu:/var/log$ cp dpkg.log /home/reader/
reader@ubuntu:/var/log$ ls -l /home/reader/
total 552
-rw-r--r-- 1 reader reader 550975 Aug 18 14:20 dpkg.log
-rw-rw-r-- 1 reader reader 69 Jul 14 13:18 nanofile.txt
drwxrwxr-x 2 reader reader 4096 Aug 4 16:16 testdir
-rwxr-xr-- 1 reader reader 0 Aug 4 13:44 testfile
-rwxr-xr-- 1 reader reader 0 Aug 18 14:00 testfilecopy
drwxrwx--- 2 reader reader 4096 Aug 4 16:18 umaskdir
-rw-rw---- 1 reader games 0 Aug 4 16:18 umaskfile
reader@ubuntu:/var/log$ cp tallylog /home/reader/
cp: cannot open 'tallylog' for reading: Permission denied
reader@ubuntu:/var/log$
那么,发生了什么?我们使用cd
将目录更改为/var/log/
。我们使用ls
和长的选项列出了那里的文件。我们复制了一个文件到完全限定的/home/reader/
目录,该文件具有我们能够读取的相对路径,但该路径属于root:root
。当我们用完全限定路径列出/home/reader/
时,我们看到复制的文件现在归reader:reader
所有。当我们试图对tallylog
文件执行同样的操作时,我们得到了错误cannot open 'tallylog' for reading: Permission denied
。这应该是意料之外的,因为我们对该文件没有任何读取权限,所以复制会很困难。
这应该回答三个问题中的两个。但是目录呢?让我们尝试将/tmp/
目录复制到我们的home
目录中:
reader@ubuntu:/var/log$ cd
reader@ubuntu:~$ cp /tmp/ .
cp: -r not specified; omitting directory '/tmp/'
reader@ubuntu:~$ ls -l
total 552
-rw-r--r-- 1 reader reader 550975 Aug 18 14:20 dpkg.log
-rw-rw-r-- 1 reader reader 69 Jul 14 13:18 nanofile.txt
drwxrwxr-x 2 reader reader 4096 Aug 4 16:16 testdir
-rwxr-xr-- 1 reader reader 0 Aug 4 13:44 testfile
-rwxr-xr-- 1 reader reader 0 Aug 18 14:00 testfilecopy
drwxrwx--- 2 reader reader 4096 Aug 4 16:18 umaskdir
-rw-rw---- 1 reader games 0 Aug 4 16:18 umaskfile
reader@ubuntu:~$ cp -r /tmp/ .
cp: cannot access '/tmp/systemd-private-72bcf47b69464914b021b421d5999bbe-systemd-timesyncd.service-LeF05x': Permission denied
cp: cannot access '/tmp/systemd-private-72bcf47b69464914b021b421d5999bbe-systemd-resolved.service-ApdzhW': Permission denied
reader@ubuntu:~$ ls -l
total 556
-rw-r--r-- 1 reader reader 550975 Aug 18 14:20 dpkg.log
-rw-rw-r-- 1 reader reader 69 Jul 14 13:18 nanofile.txt
drwxrwxr-x 2 reader reader 4096 Aug 4 16:16 testdir
-rwxr-xr-- 1 reader reader 0 Aug 4 13:44 testfile
-rwxr-xr-- 1 reader reader 0 Aug 18 14:00 testfilecopy
drwxrwxr-t 9 reader reader 4096 Aug 18 14:38 tmp
drwxrwx--- 2 reader reader 4096 Aug 4 16:18 umaskdir
-rw-rw---- 1 reader games 0 Aug 4 16:18 umaskfile
reader@ubuntu:~$
对于这样一个简单的练习,其实发生了很多!首先,我们使用cd
导航回我们的home
目录,没有任何参数;一个巧妙的小把戏。接下来,我们尝试将整个/tmp/
目录复制到.
(您应该记得,这是当前目录的简写)。然而,这个错误失败了-r not specified; omitting directory '/tmp/'
。我们列出目录来检查这一点,事实上,似乎什么都没发生。当我们添加-r
时,如错误所指定的,重试命令,我们会得到一些Permission denied
错误。这并不出乎意料,因为并非/tmp/
目录中的所有文件对我们来说都是可读的。即使我们得到了错误,当我们现在检查我们的home
目录的内容时,我们可以在那里看到tmp
目录!因此,使用-r
选项,也就是--recursive
的缩写,允许我们复制目录和目录中的所有内容。
在将一些文件和目录复制到我们的home
目录后(这是一个安全的赌注,因为我们肯定知道我们可以在那里写!),我们就剩下一点点烂摊子。让我们使用rm
命令删除一些重复的项目,而不是只创建文件:
reader@ubuntu:~$ ls -l
total 556
-rw-r--r-- 1 reader reader 550975 Aug 18 14:20 dpkg.log
-rw-rw-r-- 1 reader reader 69 Jul 14 13:18 nanofile.txt
drwxrwxr-x 2 reader reader 4096 Aug 4 16:16 testdir
-rwxr-xr-- 1 reader reader 0 Aug 4 13:44 testfile
-rwxr-xr-- 1 reader reader 0 Aug 18 14:00 testfilecopy
drwxrwxr-t 9 reader reader 4096 Aug 18 14:38 tmp
drwxrwx--- 2 reader reader 4096 Aug 4 16:18 umaskdir
-rw-rw---- 1 reader games 0 Aug 4 16:18 umaskfile
reader@ubuntu:~$ rm testfilecopy
reader@ubuntu:~$ rm tmp/
rm: cannot remove 'tmp/': Is a directory
reader@ubuntu:~$ rm -r tmp/
reader@ubuntu:~$ ls -l
total 552
-rw-r--r-- 1 reader reader 550975 Aug 18 14:20 dpkg.log
-rw-rw-r-- 1 reader reader 69 Jul 14 13:18 nanofile.txt
drwxrwxr-x 2 reader reader 4096 Aug 4 16:16 testdir
-rwxr-xr-- 1 reader reader 0 Aug 4 13:44 testfile
drwxrwx--- 2 reader reader 4096 Aug 4 16:18 umaskdir
-rw-rw---- 1 reader games 0 Aug 4 16:18 umaskfile
reader@ubuntu:~$
使用后跟文件名的rm
将其删除。正如你可能注意到的,没有。你确定吗?提示。这实际上可以通过使用-i
标志来启用,但默认情况下并非如此。考虑到rm
也允许你使用通配符,比如*
(匹配所有内容),它会删除所有匹配的文件(并且可以被用户删除)。简而言之,这是一个快速丢失文件的好方法!然而,当我们试图将rm
与目录名一起使用时,它给出了错误cannot remove 'tmp/': Is a directory
。这个和cp
命令很像,幸运的是我们的补救也是一样的:加-r
为一个递归删除!同样,这是丢失文件的好方法;一个命令就能让你删除整个home
目录和目录中的所有内容,甚至没有警告。考虑这个你的警告!特别是与--force
的简称-f
标志结合使用时,会保证rm
永远不会提示而马上开始删除。
有时,我们不只是想创建或删除一个文件,我们可能需要重命名一个文件。奇怪的是,Linux 没有任何听起来像重命名的东西;然而,mv
命令(针对 m o v e)确实实现了我们想要的功能。类似于cp
命令,它以源文件和目标文件作为参数,如下所示:
reader@ubuntu:~$ ls -l
total 552
-rw-r--r-- 1 reader reader 550975 Aug 18 14:20 dpkg.log
-rw-rw-r-- 1 reader reader 69 Jul 14 13:18 nanofile.txt
drwxrwxr-x 2 reader reader 4096 Aug 4 16:16 testdir
-rwxr-xr-- 1 reader reader 0 Aug 4 13:44 testfile
drwxrwx--- 2 reader reader 4096 Aug 4 16:18 umaskdir
-rw-rw---- 1 reader games 0 Aug 4 16:18 umaskfile
reader@ubuntu:~$ mv testfile renamedtestfile
reader@ubuntu:~$ mv testdir/ renamedtestdir
reader@ubuntu:~$ ls -l
total 552
-rw-r--r-- 1 reader reader 550975 Aug 18 14:20 dpkg.log
-rw-rw-r-- 1 reader reader 69 Jul 14 13:18 nanofile.txt
drwxrwxr-x 2 reader reader 4096 Aug 4 16:16 renamedtestdir
-rwxr-xr-- 1 reader reader 0 Aug 4 13:44 renamedtestfile
drwxrwx--- 2 reader reader 4096 Aug 4 16:18 umaskdir
-rw-rw---- 1 reader games 0 Aug 4 16:18 umaskfile
reader@ubuntu:~$
可以看到,mv
命令使用起来真的很简单。它甚至适用于目录,不需要特殊选项,比如我们在cp
和rm
中看到的-r
。然而,当我们引入通配符时,它确实变得有点复杂,但是现在不要担心这个。我们在前面的代码中使用的命令是相对的,但是它们完全合格或者混合使用。
有时,您会希望将文件从一个目录移动到另一个目录。仔细想想,这其实是对全限定文件名的重命名!没有数据被接触,但你只是想到达其他地方的文件。所以,使用mv umaskfile umaskdir/
将umaskfile
移动到umaskdir/
:
reader@ubuntu:~$ ls -l
total 16
-rw-r--r-- 1 reader reader 550975 Aug 18 14:20 dpkg.log
-rw-rw-r-- 1 reader reader 69 Jul 14 13:18 nanofile.txt
drwxrwxr-x 2 reader reader 4096 Aug 4 16:16 renamedtestdir
-rwxr-xr-- 1 reader reader 0 Aug 4 13:44 renamedtestfile
drwxrwx--- 2 reader reader 4096 Aug 4 16:18 umaskdir
-rw-rw---- 1 reader games 0 Aug 4 16:18 umaskfile
reader@ubuntu:~$ mv umaskfile umaskdir/
reader@ubuntu:~$ ls -l
total 16
-rw-r--r-- 1 reader reader 550975 Aug 18 14:20 dpkg.log
-rw-rw-r-- 1 reader reader 69 Jul 14 13:18 nanofile.txt
drwxrwxr-x 2 reader reader 4096 Aug 4 16:16 renamedtestdir
-rwxr-xr-- 1 reader reader 0 Aug 4 13:44 renamedtestfile
drwxrwx--- 2 reader reader 4096 Aug 19 10:37 umaskdir
reader@ubuntu:~$ ls -l umaskdir/
total 0
-rw-rw---- 1 reader games 0 Aug 4 16:18 umaskfile
reader@ubuntu:~$
最后是ln
命令,代表 l i n 王。这是 Linux 在文件之间创建链接的方式,最接近 Windows 使用的快捷方式。链接有两种类型:符号链接(也称为软链接)和硬链接。这种差异在文件系统的工作机制中有更深层次的体现:符号链接指的是文件名(或目录名),而硬链接指向存储文件或目录内容的索引节点。对于脚本,如果你使用链接,你可能会使用符号链接,所以让我们来看看那些在行动:
reader@ubuntu:~$ ls -l
total 552
-rw-r--r-- 1 reader reader 550975 Aug 18 14:20 dpkg.log
-rw-rw-r-- 1 reader reader 69 Jul 14 13:18 nanofile.txt
drwxrwxr-x 2 reader reader 4096 Aug 4 16:16 renamedtestdir
-rwxr-xr-- 1 reader reader 0 Aug 4 13:44 renamedtestfile
drwxrwx--- 2 reader reader 4096 Aug 4 16:18 umaskdir
-rw-rw---- 1 reader games 0 Aug 4 16:18 umaskfile
reader@ubuntu:~$ ln -s /var/log/auth.log
reader@ubuntu:~$ ln -s /var/log/auth.log link-to-auth.log
reader@ubuntu:~$ ln -s /tmp/
reader@ubuntu:~$ ln -s /tmp/ link-to-tmp
reader@ubuntu:~$ ls -l
total 552
lrwxrwxrwx 1 reader reader 17 Aug 18 15:07 auth.log -> /var/log/auth.log
-rw-r--r-- 1 reader reader 550975 Aug 18 14:20 dpkg.log
lrwxrwxrwx 1 reader reader 17 Aug 18 15:08 link-to-auth.log -> /var/log/auth.log
lrwxrwxrwx 1 reader reader 5 Aug 18 15:08 link-to-tmp -> /tmp/
-rw-rw-r-- 1 reader reader 69 Jul 14 13:18 nanofile.txt
drwxrwxr-x 2 reader reader 4096 Aug 4 16:16 renamedtestdir
-rwxr-xr-- 1 reader reader 0 Aug 4 13:44 renamedtestfile
lrwxrwxrwx 1 reader reader 5 Aug 18 15:08 tmp -> /tmp/
drwxrwx--- 2 reader reader 4096 Aug 4 16:18 umaskdir
-rw-rw---- 1 reader games 0 Aug 4 16:18 umaskfile
reader@ubuntu:~$
我们使用ln -s
(是--symbolic
的缩写)创建了两种类型的符号链接:首先是/var/log/auth.log
文件,然后是/tmp/
目录。我们看到了两种不同的使用方式ln -s
:如果没有第二个参数,它会创建一个与我们链接的东西同名的链接;否则,我们可以给出自己的链接名称作为第二个参数(从link-to-auth.log
和link-to-tmp/
链接可以看出)。我们现在可以通过与/home/reader/auth.log
或/home/reader/link-to-auth.log
交互来读取/var/log/auth.log
的内容。如果我们想导航到/tmp/
,我们现在可以使用/home/reader/tmp/
或/home/reader/link-to-tmp/
结合cd
。虽然这个例子在日常工作中不是特别有用(除非键入/var/log/auth.log
而不是auth.log
可以节省大量时间),但是链接可以防止文件的重复副本,同时保持容易访问。
An important concept in linking (and Linux filesystems in general) is the inode. Every file (whatever the type, so including directories) has an inode, which describes the attributes and disk block locations of that file. In this context, attributes include things like ownership and permissions, as well as last change, access and modification timestamps. In linking, soft links have their own inodes, while hard links refer to the same inode.
在继续本章的下一部分之前,使用rm
清理四个链接和复制的dpk.log
文件。如果您对如何做到这一点有疑问,请查看rm
的手册页。小提示:移除符号链接就像rm <name-of-link>
一样简单!
现在我们已经掌握了 Linux 中常见的文件操作,我们将继续讨论归档。虽然听起来很花哨,但归档只是指创建归档。一个大多数人都熟悉的例子是创建一个 ZIP 文件,这是一个归档文件。ZIP 不是特定于窗口的;这是一种档案文件格式,对 Windows、Linux、macOS 等有不同的实现。
如您所料,有许多归档文件格式。在 Linux 上,最常用的是 tarball ,它是使用tar
命令创建的(源自术语tapearchive)*。*以.tar
结尾的 tarball 文件未压缩。实际上,tarballs 几乎总是会被 Gzip 压缩,Gzip 代表 G NU zip 。这可以直接使用tar
命令(最常见)或之后使用gzip
命令(不太常见,但也可用于压缩除 tarballs 之外的文件)来完成。由于tar
是一个复杂的命令,我们将更详细地探讨最常用的标志(描述摘自tar
手册页):
| -c
、--create
| 创建新的归档。参数提供要存档的文件的名称。除非给出--no-recursion
选项,否则目录被递归存档。 |
| -x
、--extract
、--get
| 从档案中提取文件。参数是可选的。给定后,它们指定要提取的归档成员的名称。 |
| -t
、--list
| 列出档案的内容。参数是可选的。当给定时,它们指定要列出的成员的名称。 |
| -v
、--verbose
| 已处理的冗长列表文件。 |
| -f
、--file=ARCHIVE
| 使用存档文件或设备 ARCHY。 |
| -z
、--gzip
、--gunzip
、--ungzip
| 通过 Gzip 过滤存档。 |
| -C
、--directory=DIR
| 在执行任何操作之前,更改为 DIR。这个选项是顺序敏感的,也就是说,它影响后面的所有选项。 |
tar
命令对于我们如何指定这些选项非常灵活。我们可以一个接一个地呈现它们,全部放在一起,有或没有连字符,或者有长或短选项。这意味着以下创建归档的方法都是正确的,并且都可以工作:
tar czvf <archive name> <file1> <file2>
tar -czvf <archive name> <file1> <file2>
tar -c -z -v -f <archive name> <file1> <file2>
tar --create --gzip --verbose --file=<archive name> <file1> <file2>
虽然这似乎很有帮助,但也可能令人困惑。我们的建议是:选择其中一种格式并坚持下去。在本书中,我们将使用最短的形式,因此这是所有不带破折号的短选项。让我们用这个表格来创建我们的第一个档案!
reader@ubuntu:~$ ls -l
total 12
-rw-rw-r-- 1 reader reader 69 Jul 14 13:18 nanofile.txt
drwxrwxr-x 2 reader reader 4096 Aug 4 16:16 renamedtestdir
-rwxr-xr-- 1 reader reader 0 Aug 4 13:44 renamedtestfile
drwxrwx--- 2 reader reader 4096 Aug 4 16:18 umaskdir
reader@ubuntu:~$ tar czvf my-first-archive.tar.gz \
nanofile.txt renamedtestfile
nanofile.txt
renamedtestfile
reader@ubuntu:~$ ls -l
total 16
-rw-rw-r-- 1 reader reader 267 Aug 19 10:29 my-first-archive.tar.gz
-rw-rw-r-- 1 reader reader 69 Jul 14 13:18 nanofile.txt
drwxrwxr-x 2 reader reader 4096 Aug 4 16:16 renamedtestdir
-rwxr-xr-- 1 reader reader 0 Aug 4 13:44 renamedtestfile
drwxrwx--- 2 reader reader 4096 Aug 4 16:18 umaskdir
-rw-rw---- 1 reader games 0 Aug 4 16:18 umaskfile
reader@ubuntu:~$
有了这个命令,我们verbosec创建了一个名为my-first-archive.tar.gz
的 gzIPPf文件,包含文件nanofile.txt umaskfile
和renamedtestfile
。
In this example, we only archived files. In practice, it is often nice to archive an entire directory. The syntax for this is exactly the same, only instead of a filename you will give a directory name. The whole directory will be archived (and, in the case of the -z
option, compressed as well). When you unpack a tarball that archived a directory, the entire directory will be extracted again, not just the contents.
现在,让我们看看打开它是否能把我们的文件还给我们!我们将压缩的 tarball 移动到renamedtestdir
,并使用tar xzvf
命令在那里打开包装:
reader@ubuntu:~$ ls -l
total 16
-rw-rw-r-- 1 reader reader 226 Aug 19 10:40 my-first-archive.tar.gz
-rw-rw-r-- 1 reader reader 69 Jul 14 13:18 nanofile.txt
drwxrwxr-x 2 reader reader 4096 Aug 4 16:16 renamedtestdir
-rwxr-xr-- 1 reader reader 0 Aug 4 13:44 renamedtestfile
drwxrwx--- 2 reader reader 4096 Aug 19 10:37 umaskdir
reader@ubuntu:~$ mv my-first-archive.tar.gz renamedtestdir/
reader@ubuntu:~$ cd renamedtestdir/
reader@ubuntu:~/renamedtestdir$ ls -l
total 4
-rw-rw-r-- 1 reader reader 226 Aug 19 10:40 my-first-archive.tar.gz
reader@ubuntu:~/renamedtestdir$ tar xzvf my-first-archive.tar.gz
nanofile.txt
renamedtestfile
reader@ubuntu:~/renamedtestdir$ ls -l
total 8
-rw-rw-r-- 1 reader reader 226 Aug 19 10:40 my-first-archive.tar.gz
-rw-rw-r-- 1 reader reader 69 Jul 14 13:18 nanofile.txt
-rwxr-xr-- 1 reader reader 0 Aug 4 13:44 renamedtestfile
reader@ubuntu:~/renamedtestdir$
正如我们所看到的,我们把文件放回了renamedtestdir
!实际上,我们从未删除原始文件,所以这些是副本。在你不厌其烦地提取和清理所有东西之前,你可能想知道 tarball 里面有什么。这可以通过使用-t
选项而不是-x
来实现:
reader@ubuntu:~/renamedtestdir$ tar tzvf my-first-archive.tar.gz
-rw-rw-r-- reader/reader 69 2018-08-19 11:54 nanofile.txt
-rw-rw-r-- reader/reader 0 2018-08-19 11:54 renamedtestfile
reader@ubuntu:~/renamedtestdir$
最后一个广泛用于tar
的有趣选项是-C
,或--directory
选项。该命令确保我们在提取归档文件之前不必移动它。让我们用它从我们的home
目录中提取/home/reader/renamedtestdir/my-first-archive.tar.gz
到/home/reader/umaskdir/
:
reader@ubuntu:~/renamedtestdir$ cd
reader@ubuntu:~$ tar xzvf renamedtestdir/my-first-archive.tar.gz -C umaskdir/
nanofile.txt
renamedtestfile
reader@ubuntu:~$ ls -l umaskdir/
total 4
-rw-rw-r-- 1 reader reader 69 Jul 14 13:18 nanofile.txt
-rwxr-xr-- 1 reader reader 0 Aug 4 13:44 renamedtestfile
-rw-rw---- 1 reader games 0 Aug 4 16:18 umaskfile
reader@ubuntu:~$
通过在档案名称后指定目录参数-C
,我们确保tar
将 gzipped tarball 的内容提取到指定的目录中。
这涵盖了tar
命令最重要的方面。然而,还有一件小事:清理!我们已经把我们的home
目录弄得一团糟,而且我们没有任何文件可以做任何事情。下面是一个实际例子,展示了带有rm -r
命令的通配符有多危险:
reader@ubuntu:~$ ls -l
total 12
-rw-rw-r-- 1 reader reader 69 Jul 14 13:18 nanofile.txt
drwxrwxr-x 2 reader reader 4096 Aug 19 10:42 renamedtestdir
-rwxr-xr-- 1 reader reader 0 Aug 4 13:44 renamedtestfile
drwxrwx--- 2 reader reader 4096 Aug 19 10:47 umaskdir
reader@ubuntu:~$ rm -r *
reader@ubuntu:~$ ls -l
total 0
reader@ubuntu:~$
一个简单的命令,没有警告,所有文件,包括有更多文件的目录,都不见了!你应该想知道:不,Linux 也没有回收站。这些文件不见了;只有先进的硬盘恢复技术可能仍然能够恢复这些文件。
Make sure that you perform the preceding command, just to get a feeling for how destructive rm
can be. Before you do, however, ensure that you are in your home
directory and that you do not accidentally have any files there that you do not want to delete. If you followed our examples, this should not be the case, but if you've done anything else, be sure about what you're doing!
在了解了常见的文件操作和归档之后,我们还没有涉及到文件操作中的一项重要技能:查找文件。你知道如何复制或归档文件是非常好的,但是如果你找不到你想要操作的文件,你将很难完成你的任务。幸运的是,有专门用于在 Linux 文件系统上查找和定位文件的工具。而且,为了简单起见,这些被称为find
和locate
。find
命令更复杂,但更强大,而locate
命令在您确切知道您要找什么时更容易使用。首先,我们将向您展示如何使用locate
,然后进入find
更广泛的功能。
在定位的手册页上,描述再合适不过了:locate - find files by name
。locate
命令默认安装在你的 Ubuntu 机器上,基本功能就像使用locate <filename>
一样简单。让我们看看这是如何工作的:
reader@ubuntu:~$ locate fstab
/etc/fstab
/lib/systemd/system-generators/systemd-fstab-generator
/sbin/fstab-decode
/usr/share/doc/mount/examples/fstab
/usr/share/doc/mount/examples/mount.fstab
/usr/share/doc/util-linux/examples/fstab
/usr/share/doc/util-linux/examples/fstab.example2
/usr/share/man/man5/fstab.5.gz
/usr/share/man/man8/fstab-decode.8.gz
/usr/share/man/man8/systemd-fstab-generator.8.gz
/usr/share/vim/vim80/syntax/fstab.vim
reader@ubuntu:~$
在前面的例子中,我们寻找文件名fstab
。我们可能记得我们需要编辑这个文件以适应文件系统的变化,但是我们不确定在哪里可以找到它。locate
向我们展示了磁盘上包含fstab
的所有位置。如你所见,它不一定是完全匹配的;包含fstab
字符串的所有内容都将被打印。
You might have noticed that the locate
command completes almost instantly. That is because it uses a database for all files which is updated periodically, instead of going through the whole filesystem at runtime. Because of this, the information is not always accurate, since changes are not synchronized to the database in real-time. To ensure that you are talking to the database with the latest state of the filesystem, be sure to run sudo updatedb
(requires root privileges) before running locate
. This is also required before the first run of locate
on a system, because otherwise there is no database to query!
Locate 有一些选项,但根据我们的经验,只有知道确切的文件名(或文件名的确切部分),才能使用它。对于其他搜索,默认使用find
命令是一个更好的主意。
Find 是一个非常强大但复杂的命令。您可以使用find
执行以下任一操作:
- 搜索文件名
- 搜索权限(用户和组)
- 搜索所有权
- 搜索文件类型
- 搜索文件大小
- 搜索时间戳(创建时间、最后修改时间、最后访问时间)
- 仅在特定目录中搜索
解释find
命令中的所有功能需要一整章的时间。我们将只描述最常见的用例。这里真正的教训是意识到find
的高级功能;如果您需要查找具有特定属性的文件,请首先考虑find
命令,并查看man file
页面,看您是否可以利用“查找”进行搜索(剧透提醒:这几乎总是的情况!).
先从 find: find <location> <options and arguments>
的基本用法说起。如果没有任何选项和参数,find 将打印它在以下位置找到的每个文件:
reader@ubuntu:~$ find /home/reader/
/home/reader/
/home/reader/.gnupg
/home/reader/.gnupg/private-keys-v1.d
/home/reader/.bash_logout
/home/reader/.sudo_as_admin_successful
/home/reader/.profile
/home/reader/.bashrc
/home/reader/.viminfo
/home/reader/.lesshst
/home/reader/.local
/home/reader/.local/share
/home/reader/.local/share/nano
/home/reader/.cache
/home/reader/.cache/motd.legal-displayed
/home/reader/.bash_history
reader@ubuntu:~$
你可能以为你的home
目录是空的。它实际上包含了相当多的隐藏文件或目录(以一个点开始),这是find
为我们找到的。现在,让我们应用带有-name
选项的过滤器:
reader@ubuntu:~$ find /home/reader/ -name bash
reader@ubuntu:~$ find /home/reader/ -name *bash*
/home/reader/.bash_logout
/home/reader/.bashrc
/home/reader/.bash_history
reader@ubuntu:~$ find /home/reader/ -name .bashrc
/home/reader/.bashrc
reader@ubuntu:~$
与您可能预期的相反,就部分匹配的文件而言,find
的工作方式与locate
不同。除非您在-name
的参数周围添加通配符,否则它只会匹配完整的文件名,而不会匹配部分匹配的文件。这绝对是需要记住的事情。现在,只查找文件而不是目录怎么样?为此,我们可以对目录使用-type
选项,对文件使用d
参数:
reader@ubuntu:~$ find /home/reader/ -type d
/home/reader/
/home/reader/.gnupg
/home/reader/.gnupg/private-keys-v1.d
/home/reader/.local
/home/reader/.local/share
/home/reader/.local/share/nano
/home/reader/.cache
reader@ubuntu:~$ find /home/reader/ -type f
/home/reader/.bash_logout
/home/reader/.sudo_as_admin_successful
/home/reader/.profile
/home/reader/.bashrc
/home/reader/.viminfo
/home/reader/.lesshst
/home/reader/.cache/motd.legal-displayed
/home/reader/.bash_history
reader@ubuntu:~$
第一个结果显示/home/reader/
内的所有目录(包括/home/reader/!
),而第二个结果打印所有文件。正如你所看到的,没有重叠,因为 Linux 下的文件总是只有一种类型。我们还可以组合多个选项,如-name
和-type
:
reader@ubuntu:~$ find /home/reader/ -name *cache* -type f
reader@ubuntu:~$ find /home/reader/ -name *cache* -type d
/home/reader/.cache
reader@ubuntu:~$
我们从在包含字符串缓存的/home/reader/
中寻找文件开始。find
命令不打印任何内容,这意味着我们没有找到任何内容。然而,如果我们使用缓存字符串查找目录,我们会看到/home/reader/.cache/
目录。
作为最后一个例子,让我们看看如何使用find
来区分不同大小的文件。为此,我们将使用touch
创建一个空文件,并使用vim
(或nano
)创建一个非空文件:
reader@ubuntu:~$ ls -l
total 0
reader@ubuntu:~$ touch emptyfile
reader@ubuntu:~$ vim textfile.txt
reader@ubuntu:~$ ls -l
total 4
-rw-rw-r-- 1 reader reader 0 Aug 19 11:54 emptyfile
-rw-rw-r-- 1 reader reader 23 Aug 19 11:54 textfile.txt
reader@ubuntu:~
从屏幕上的0
和23
可以看到,emptyfile
包含 0 个字节,而textfile.txt
包含 23 个字节(并非完全巧合,包含一个 23 个字符的句子)。让我们看看如何使用find
命令找到这两个文件:
reader@ubuntu:~$ find /home/reader/ -size 0c
/home/reader/.sudo_as_admin_successful
/home/reader/.cache/motd.legal-displayed
/home/reader/emptyfile
reader@ubuntu:~$ find /home/reader/ -size 23c
/home/reader/textfile.txt
reader@ubuntu:~$
为此,我们使用-size
选项。我们给它一个我们要找的数字,后跟一个字母,表示我们要处理的范围。c
用于字节,k
用于千字节,M
用于兆字节,以此类推。您可以在手册页上找到这些值。结果显示,有三个文件正好是 0 字节:我们的emptyfile
就是其中之一。这是一个正好 23 字节的文件:我们的textfile.txt
。你可能会想:23 字节,这很具体!我们怎么知道一个文件到底有多少字节?你不会的。find
的创作者还实现了一个大于的和小于的构造,我们可以用它来给我们多一点灵活性:
reader@ubuntu:~$ find /home/reader/ -size +10c
/home/reader/
/home/reader/.gnupg
/home/reader/.gnupg/private-keys-v1.d
/home/reader/.bash_logout
/home/reader/.profile
/home/reader/.bashrc
/home/reader/.viminfo
/home/reader/.lesshst
/home/reader/textfile.txt
/home/reader/.local
/home/reader/.local/share
/home/reader/.local/share/nano
/home/reader/.cache
/home/reader/.bash_history
reader@ubuntu:~$ find /home/reader/ -size +10c -size -30c
/home/reader/textfile.txt
reader@ubuntu:~$
假设我们正在寻找一个至少大于 10 字节的文件。我们在参数上使用+
选项,它只打印大于 10 字节的文件。然而,我们仍然看到太多的文件。现在,我们希望文件也小于 30 字节。我们添加了另一个-size
选项,这次指定了-30c
,这意味着文件将少于 30 字节。而且,并非完全出乎意料,我们的 23 字节testfile.txt
被找到了!
前面的所有选项以及更多选项可以组合起来形成一个非常强大的搜索查询。你在找一个文件,至少是100 KB 但是不超过* 10 MB,位于* /var/
的某个地方*,是上周创建的,对你来说可读吗?只要结合find
中的选项,你一定会很快找到那个文件!*
本章描述了 Linux 中的文件操作。我们从常见的文件操作开始。我们解释了如何使用cp
在 Linux 中复制文件,以及如何使用mv
移动或重命名文件。接下来,我们讨论了如何使用rm
删除文件和目录,以及如何使用ln -s
命令在带有符号链接的 Linux 下创建快捷方式。
在本章的第二部分,我们讨论了归档。虽然有许多不同的工具允许归档,但我们关注的是 Linux 中最常用的工具:tar
。我们向您展示了如何在当前工作目录中和文件系统的其他地方创建和提取归档。我们描述了文件和整个目录都可以由tar
存档,并且我们可以看到 tarball 中的内容,而无需使用-t
选项实际提取它。
我们以使用file
和locate
查找文件来结束本章。我们解释了locate
是一个简单的命令,在某些情况下是有用的,而find
是一个更复杂但非常强大的命令,可以为掌握它的人提供巨大的好处。
本章介绍了以下命令:cp
、rm
、mv
、ln
、tar
、locate
和find
。
- 在 Linux 中,我们使用哪个命令来复制文件?
- 移动和重命名文件有什么区别?
- 为什么用来删除 Linux 下文件的
rm
命令有潜在危险? - 硬链接和符号(软)链接有什么区别?
tar
最重要的三种运行模式是什么?tar
用哪个选项选择输出目录?- 在文件名上搜索
locate
和find
最大的区别是什么? find
可以组合多少个选项?
如果您想深入了解本章的主题,以下资源可能会很有意思: