文件系统
Linux将文件存储在单个目录结构中,这个目录被称为虚拟目录(virtual directory)。虚拟目录将安装在PC上的所有存储设备的文件路径纳入单个目录结构中。Linux虚拟目录结构只包含一个称为根(root)目录的基础目录。
在Linux中,你会看到下面这种路径:
/home/Rich/Documents/test.doc
这表明文件test.doc位于Documents目录,Documents又位于rich目录中,rich则在home目录中。要注意的是,路径本身并没有提供任何有关文件究竟存放在哪个物理磁盘上的信息。
Linux虚拟目录中比较复杂的部分是它如何协调管理各个存储设备。在Linux PC上安装的第一块硬盘称为根驱动器。根驱动器包含了虚拟目录的核心,其他目录都是从那里开始构建的。
Linux会在根驱动器上创建一些特别的目录,我们称之为挂载点(mount point)。挂载点是虚拟目录中用于分配额外存储设备的目录。虚拟目录会让文件和目录出现在这些挂载点目录中,然而实际上它们却存储在另外一个驱动器中。
通常系统文件会存储在根驱动器中,而用户文件则存储在另一驱动器中。一块硬盘和虚拟目录的根目录(由正斜线/表示)关联起来。剩下的硬盘就可以挂载到虚拟目录结构中的任何地方。在这个例子中,第二块硬盘被挂载到了/home位置,用户目录都位于这个位置。
表3-3列出了一些较常见的Linux顶层虚拟目录名及其内容。
目录命令
遍历目录
cd
cd destination
cd命令可接受单个参数destination,用以指定想切换到的目录名。如果没有为cd命令指定目标路径,它将切换到用户主目录。
destination参数可以用两种方式表示:一种是使用绝对文件路径,另一种是使用相对文件路径。
有两个特殊字符可用于相对文件路径中:
- 单点符(.),表示当前目录;
- 双点符(..),表示当前目录的父目录。
pwd
pwd命令可以显示出shell会话的当前目录,这个目录被称为当前工作目录
创建目录
mkdir
在Linux中创建目录很简单,用mkdir命令即可:
$ mkdir New_Dir
$ ls -ld New_Dir
drwxrwxr-x 2 christine christine 4096 May 22 09:48 New_Dir
$
系统创建了一个名为New_Dir的新目录。注意,新目录长列表是以d开头的。这表示New_Dir并不是文件,而是一个目录。
可以根据需要批量地创建目录和子目录。但是,如果你想单单靠mkdir命令来实现,就会得到下面的错误消息:
$ mkdir New_Dir/Sub_Dir/Under_Dir
mkdir: cannot create directory 'New_Dir/Sub_Dir/Under_Dir':
No such file or directory
$
要想同时创建多个目录和子目录,需要加入-p参数:
$ mkdir -p New_Dir/Sub_Dir/Under_Dir
$
$ ls -R New_Dir
New_Dir:
Sub_Dir
New_Dir/Sub_Dir:
Under_Dir
New_Dir/Sub_Dir/Under_Dir:
$
删除目录
rmdir
默认情况下,rmdir命令只删除空目录。
要解决这一问题,得先把目录中的文件删掉,然后才能在空目录上使用rmdir命令。
$ rm -i New_Dir/my_file
rm: remove regular empty file 'New_Dir/my_file'? y
$
$ rmdir New_Dir
$
$ ls -ld New_Dir
ls: cannot access New_Dir: No such file or directory
rmdir并没有-i选项来询问是否要删除目录。也可以在整个非空目录上使用rm命令。使用-r选项使得命令可以向下进入目录,删除其中的文件,然后再删除目录本身。
文件命令
创建文件
touch
touch test_one
touch命令创建了你指定的新文件,并将你的用户名作为文件的属主。
删除文件
rm
在Linux中,删除(deleting)叫作移除(removing)①。bash shell中删除文件的命令是rm。rm命令的基本格式非常简单。
$ rm -i fall
rm: remove regular empty file 'fall'? y
$
$ ls -l fall
ls: cannot access fall: No such file or directory
$
**注意,-i命令参数提示你是不是要真的删除该文件。**bash shell中没有回收站或垃圾箱,文件一旦删除,就无法再找回。因此,在使用rm命令时,要养成总是加入-i参数的好习惯。
-r参数可以递归地删除目录中的文件。
一口气删除目录及其所有内容的终极大法就是使用带有-r参数和-f参数的rm命令。rm -rf命令既没有警告信息,也没有声音提示。这肯定是一个危险的工具,尤其是在拥有超级用户权限的时候。
也可以使用通配符删除成组的文件。rm命令的另外一个特性是,如果要删除很多文件且不受提示符的打扰,可以用-f参数强制删除。小心为妙!
查看文件内容
file
file命令是一个随手可得的便捷工具。它能够探测文件的内部,并决定文件是什么类型的:
$ file my_file
my_file: ASCII text
$
上面例子中的文件是一个text(文本)文件。file命令不仅能确定文件中包含的文本信息,还能确定该文本文件的字符编码,ASCII。
下面例子中的文件就是一个目录。因此,以后可以使用file命令作为另一种区分目录的方法:
$ file New_Dir
New_Dir: directory
$
cat
cat命令是显示文本文件中所有数据的得力工具。
$ cat test1
hello
This is a test file.
That we'll use to test the cat command.
$
没什么特别的,就是文本文件的内容而已。常用参数有:
- -n:会给所有的行加上行号。
- -b:这个功能在检查脚本时很有用。如果只想给有文本的行加上行号,可以用-b参数。
more
cat命令的主要缺陷是:一旦运行,你就无法控制后面的操作。为了解决这个问题,开发人员编写了more命令。more命令会显示文本文件的内容,但会在显示每页数据之后停下来。
more命令是分页工具,你可以通过按空格键或回车键以逐行向前的方式浏览文本文件。浏览完之后,按q键退出。
more命令只支持文本文件中的基本移动。如果要更多高级功能,可以试试less命令。
less
less命令的操作和more命令基本一样,一次显示一屏的文件文本。除了支持和more命令相同的命令集,它还包括更多的选项。
tail
通常你要查看的数据要么在文本文件的开头,要么在文本文件的末尾。如果这些数据是在大型文件的起始部分,那你就得等cat或more加载完整个文件之后才能看到。如果数据是在文件的末尾(比如日志文件),那可能需要翻过成千上万行的文本才能到最后的内容。好在Linux有解决这两个问题的专用命令。这两个命令都允许你在破折号后面输入想要显示的行数:
$ head/tail -5 log_file
tail命令默认浏览文件最后10行的效果。
可以向tail命令中加入-n参数来修改所显示的行数,在下面的例子中,通过加入-n 2使tail命令只显示文件的最后两行:
$ tail -n 2 log_file
line19
Last line - line20
$
-f参数是tail命令的一个突出特性。它允许你在其他进程使用该文件时查看文件的内容。tail命令会保持活动状态,并不断显示添加到文件中的内容。这是实时监测系统日志的绝妙方式。
head
head命令,顾名思义,会显示文件开头那些行的内容。默认情况下,它会显示文件前10行的文本。
类似于tail命令,它也支持-n参数,文件的开头通常不会改变,因此head命令并像tail命令那样支持-f参数特性。
文件与目录命令
ls
ls命令最基本的形式会显示当前目录下的文件和目录
常用参数:
- -F:区分文件和目录,该参数在目录名后加了正斜线(/),以方便用户在输出中分辨它们
- -a:把隐藏文件和普通文件及目录一起显示出来。在Linux上,隐藏文件通常是文件名以点号开始的文件。
- -R:递归选项。它列出了当前目录下包含的子目录中的文件。
- -l:产生长列表格式的输出,包含了目录中每个文件的更多相关信息。
ls命令还支持在命令行中定义过滤器。它会用过滤器来决定应该在输出中显示哪些文件或目录。这个过滤器就是一个进行简单文本匹配的字符串。可以在要用的命令行参数之后添加这个过滤器:
$ ls -l my_script
-rwxrw-r-- 1 christine christine 54 May 21 11:26 my_script
$
ls命令能够识别标准通配符,并在过滤器中用它们进行模式匹配:
-
问号(?)代表一个字符;
-
星号(*)代表零个或多个字符。
可以使用中括号。
$ ls -l my_scr[ai]pt
-rw-rw-r-- 1 christine christine 0 May 21 13:25 my_scrapt
-rwxrw-r-- 1 christine christine 54 May 21 11:26 my_script
$
在这个例子中,我们使用了中括号以及在特定位置上可能出现的两种字符:a或i。中括号表示一个字符位置并给出多个可能的选择。可以像上面的例子那样将待选的字符列出来,也可以指定字符范围,例如字母范围[a – i]。
另外,可以使用感叹号(!)将不需要的内容排除在外。
$ ls -l f[!a]ll
cp
可以在cp命令中使用通配符。
复制文件
cp source destination
当source和destination参数都是文件名时,cp命令将源文件复制成一个新文件,并且以destination命名。新文件就像全新的文件一样,有新的修改时间。
$ cp test_one test_two
$ ls -l test_*
-rw-rw-r-- 1 christine christine 0 May 21 14:35 test_one
-rw-rw-r-- 1 christine christine 0 May 21 15:15 test_two
$
新文件test_two和文件test_one的修改时间并不一样。如果目标文件已经存在,cp命令可能并不会提醒这一点。最好是加上-i选项,强制shell询问是否需要覆盖已有文件。
$ ls -l test_*
-rw-rw-r-- 1 christine christine 0 May 21 14:35 test_one
-rw-rw-r-- 1 christine christine 0 May 21 15:15 test_two
$
$ cp -i test_one test_two
cp: overwrite 'test_two'? n
$
如果不回答y,文件复制将不会继续。也可以将文件复制到现有目录中。
复制目录
cp命令的-R参数威力强大。可以用它在一条命令中递归地复制整个目录的内容。
$ cp -R Scripts/ Mod_Scripts
$ ls -Fd *Scripts
Mod_Scripts/ Scripts/
$ ls -l Mod_Scripts
total 25
-rwxrw-r-- 1 christine christine 929 May 21 16:16 file_mod.sh
-rwxrw-r-- 1 christine christine 254 May 21 16:16 SGID_search.sh
-rwxrw-r-- 1 christine christine 243 May 21 16:16 SUID_search.sh
$
在执行cp –R命令之前,目录Mod_Scripts并不存在。它是随着cp –R命令被创建的,整个Scripts目录中的内容都被复制到其中。注意,在新的Mod_Scripts目录中,所有的文件都有对应的新日期。Mod_Scripts目录现在已经成为了Scripts目录的完整副本。
移动或重命名文件/目录
mv
在Linux中,重命名文件称为移动(moving)。mv命令可以将文件和目录移动到另一个位置或重新命名。
$ mv fall fzll
移动文件会将文件名从fall更改为fzll,但inode编号和时间戳保持不变。这是因为mv只影响文件名。
也可以使用mv来移动文件的位置。
$ mv fzll Pictures/
我们使用mv命令把文件fzll从/home/christine移动到了/home/christine/Pirctures。和cp命令类似,也可以在mv命令中使用-i参数。这样在命令试图覆盖已有的文件时,你就会得到提示。
$ mv /home/christine/Pictures/fzll /home/christine/fall
在这个例子中,我们将文件fzll从子目录Pictures中移动到了主目录/home/christine,并将名字改为fall。文件的时间戳和inode编号都没有改变。改变的只有位置和名称。
也可以使用mv命令移动整个目录及其内容。
内容来源
[1] [美] Richard Blum Christine Bresnahan.Linux命令行与shell脚本编程大全(第3版).北京人民邮电出版社,2016.