命令/参数 | 备注 |
---|---|
touch | 创建空文件 |
-a | 改变访问时间 |
命令/参数 | 备注 |
---|---|
cp | 复制文件 |
cp test_one test_two | 复制test_one为test_two,test_two已存在会覆盖 |
-i | 强制shell询问是否需要覆盖已有文件 |
-R | 在一条命令中递归地复制整个目录的内容,并且会创建文件夹 |
你总会时不时地遇到要创建空文件的情况。例如,有时应用程序希望在它们写入数据之前,某个日志文件已经存在。这时,可用touch命令轻松创建空文件。
$ touch test_one
$ ls -l test_one
-rw-rw-r-- 1 christine christine 0 May 21 14:17 test_one
$
touch命令创建了你指定的新文件,并将你的用户名作为文件的属主。注意,文件的大小是零,因为touch命令只创建了一个空文件。
touch命令还可用来改变文件的修改时间。这个操作并不需要改变文件的内容。
$ ls -l test_one
-rw-rw-r-- 1 christine christine 0 May 21 14:17 test_one
$ touch test_one
$ ls -l test_one
-rw-rw-r-- 1 christine christine 0 May 21 14:35 test_one
$
test_one文件的修改时间现在已经从最初的时间14:17更新到了14:35。如果只想改变访问时间,可用-a参数。
$ ls -l test_one
-rw-rw-r-- 1 christine christine 0 May 21 14:35 test_one
$ touch -a test_one
$ ls -l test_one
-rw-rw-r-- 1 christine christine 0 May 21 14:35 test_one
$ ls -l --time=atime test_one
-rw-rw-r-- 1 christine christine 0 May 21 14:55 test_one
$
在上面的例子中,要注意的是,如果只使用ls –l命令,并不会显示访问时间。这是因为默认显示的是修改时间。要想查看文件的访问时间,需要加入另外一个参数:–time=atime。有了这个参数,就能够显示出已经更改过的文件访问时间。
创建空文件和更改文件时间戳算不上你在Linux系统中的日常工作。不过复制文件可是在使用shell时经常要干的活儿。
对系统管理员来说,在文件系统中将文件和目录从一个位置复制到另一个位置可谓家常便饭。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 -i test_one /home/christine/Documents/
$
$ ls -l /home/christine/Documents
total 0
-rw-rw-r-- 1 christine christine 0 May 21 15:25 test_one
$
新文件现就在目录Documents中了,和源文件同名。
之前的例子在目标目录名尾部加上了一个正斜线(/),这表明Documents是目录而非文件。这有助于明确目的,而且在复制单个文件时非常重要。如果没有使用正斜线,子目录/home/christine/Documents又不存在,就会有麻烦。在这种情况下,试图将一个文件复制到Documents子目录反而会创建一个名为Documents的文件,连错误消息都不会显示!
上一个例子采用了绝对路径,不过也可以使用相对路径。
$ cp -i test_one Documents/
cp: overwrite 'Documents/test_one'? y
$
$ ls -l Documents
total 0
-rw-rw-r-- 1 christine christine 0 May 21 15:28 test_one
$
本章在前面介绍了特殊符号可以用在相对文件路径中。其中的单点符(.)就很适合用于cp命令。记住,单点符表示当前工作目录。如果需要将一个带有很长的源对象名的文件复制到当前工作目录中时,单点符能够简化该任务。
$ cp -i /etc/NetworkManager/NetworkManager.conf .
$
$ ls -l NetworkManager.conf
-rw-r--r-- 1 christine christine 76 May 21 15:55 NetworkManager.conf
$
想找到那个单点符可真是不容易!仔细看的话,你会发现它在第一行命令的末尾。如果你的源对象名很长,使用单点符要比输入完整的目标对象名省事得多。
cp命令的参数要比这里叙述的多得多。别忘了用man cp,你可以看到cp命令所有的可用参数。
cp命令的-R参数威力强大。可以用它在一条命令中递归地复制整个目录的内容。
$ ls -Fd *Scripts
Scripts/
$ ls -l Scripts/
total 25
-rwxrw-r-- 1 christine christine 929 Apr 2 08:23 file_mod.sh
-rwxrw-r-- 1 christine christine 254 Jan 2 14:18 SGID_search.sh
-rwxrw-r-- 1 christine christine 243 Jan 2 13:42 SUID_search.sh
$
$ 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目录的完整副本。
在上面的例子中,ls命令加入了-Fd选项。之前你已经见过-F选项了,不过-d选项可能还是第一次碰到。后者只列出目录本身的信息,不列出其中的内容。
也可以在cp命令中使用通配符。
$ cp *script Mod_Scripts/
$ ls -l Mod_Scripts
total 26
-rwxrw-r-- 1 christine christine 929 May 21 16:16 file_mod.sh
-rwxrw-r-- 1 christine christine 54 May 21 16:27 my_script
-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
$
该命令将所有以script结尾的文件复制到Mod_Scripts目录中。在这里,只需要复制一个文件:my_script。
在复制文件的时候,除了单点符和通配符之外,另一个shell特性也能派上用场。那就是制表键自动补全。
在使用命令行时,很容易输错命令、目录名或文件名。实际上,对长目录名或文件名来说,输错的几率还是蛮高的。
这正是制表键自动补全挺身而出的时候。制表键自动补全允许你在输入文件名或目录名时按一下制表键,让shell帮忙将内容补充完整。
$ ls really*
really_ridiculously_long_file_name
$
$ cp really_ridiculously_long_file_name Mod_Scripts/
ls -l Mod_Scripts
total 26
-rwxrw-r-- 1 christine christine 929 May 21 16:16 file_mod.sh
-rwxrw-r-- 1 christine christine 54 May 21 16:27 my_script
-rw-rw-r-- 1 christine christine 0 May 21 17:08
really_ridiculously_long_file_name
-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 really,然后按制表键,shell就将剩下的文件名自动补充完整了!当然了,目标目录还是得输入的,不过仍然可以利用命令补全来避免输入错误。
使用制表键自动补全的的技巧在于要给shell足够的文件名信息,使其能够将需要文件同其他文件区分开。假如有另一个文件名也是以really开头,那么就算按了制表键,也无法完成文件名的自动补全。这时候你会听到嘟的一声。要是再按一下制表键,shell就会列出所有以really开头的文件名。这个特性可以让你观察究竟应该输入哪些内容才能完成自动补全。
链接文件是Linux文件系统的一个优势。如需要在系统上维护同一文件的两份或多份副本,除了保存多份单独的物理文件副本之外,还可以采用保存一份物理文件副本和多个虚拟副本的方法。这种虚拟的副本就称为链接。链接是目录中指向文件真实位置的占位符。在Linux中有两种不同类型的文件链接:
符号链接
硬链接
符号链接就是一个实实在在的文件,它指向
存放在虚拟目录结构中某个地方的另一个文件。这两个通过符号链接在一起的文件,彼此的内容并不相同。
要为一个文件创建符号链接,原始文件必须事先存在。然后可以使用ln命令以及-s选项来创建符号链接。
$ ls -l data_file
-rw-rw-r-- 1 christine christine 1092 May 21 17:27 data_file
$
$ ln -s data_file sl_data_file
$
$ ls -l *data_file
-rw-rw-r-- 1 christine christine 1092 May 21 17:27 data_file
lrwxrwxrwx 1 christine christine 9 May 21 17:29 sl_data_file -> data_file
$
在上面的例子中,注意符号链接的名字sl_data_file位于ln命令中的第二个参数位置上。显示在长列表中符号文件名后的->符号表明该文件是链接到文件data_file上的一个符号链接。
另外还要注意的是,符号链接的文件大小与数据文件的文件大小。符号链接sl_data_file只有9个字节,而data_file有1092个字节。这是因为sl_data_file仅仅只是指向data_file而已。它们的内容并不相同,是两个完全不同的文件。
另一种证明链接文件是独立文件的方法是查看inode编号。文件或目录的inode编号是一个用于标识的唯一数字,这个数字由内核分配给文件系统中的每一个对象。要查看文件或目录的inode编号,可以给ls命令加入-i参数。
$ ls -i *data_file
296890 data_file 296891 sl_data_file
$
从这个例子中可以看出数据文件的inode编号是296890,而sl_data_file的inode编号则是296891。所以说它们是不同的文件。
硬链接会创建独立的虚拟文件,其中包含了原始文件的信息及位置。但是它们从根本上而言是同一个文件
。引用硬链接文件等同于引用了源文件。要创建硬链接,原始文件也必须事先存在,
只不过这次使用ln命令时不再需要加入额外的参数了。
$ ls -l code_file
-rw-rw-r-- 1 christine christine 189 May 21 17:56 code_file
$
$ ln code_file hl_code_file
$
$ ls -li *code_file
296892 -rw-rw-r-- 2 christine christine 189 May 21 17:56
code_file
296892 -rw-rw-r-- 2 christine christine 189 May 21 17:56
hl_code_file
$
在上面的例子中,我们使用ls -li命令显示了*code_files的inode编号以及长列表。注意,带有硬链接的文件共享inode编号。这是因为它们终归是同一个文件。还要注意的是,链接计数(列表中第三项)显示这两个文件都有两个链接。另外,它们的文件大小也一模一样。
只能对处于同一存储媒体的文件创建硬链接。要想在不同存储媒体的文件之间创建链接,只能使用符号链接。
复制链接文件的时候一定要小心。如果使用cp命令复制一个文件,而该文件又已经被链接到了另一个源文件上,那么你得到的其实是源文件的一个副本。这很容易让人犯晕。用不着复制链接文件,可以创建原始文件的另一个链接。同一个文件拥有多个链接,这完全没有问题。
但是,千万别创建软链接文件的软链接。这会形成混乱的链接链,不仅容易断裂,还会造成各种麻烦。
你可能觉得符号链接和硬链接的概念不好理解。幸好下一节中的文件重命名容易明白得多。
在Linux中,重命名文件称为移动(moving)。mv命令可以将文件和目录移动到另一个位置或重新命名。
$ ls -li f?ll
296730 -rw-rw-r-- 1 christine christine 0 May 21 13:44 fall
296717 -rw-rw-r-- 1 christine christine 0 May 21 13:44 fell
294561 -rw-rw-r-- 1 christine christine 0 May 21 13:44 fill
296742 -rw-rw-r-- 1 christine christine 0 May 21 13:44 full
$
$ mv fall fzll
$
$ ls -li f?ll
296717 -rw-rw-r-- 1 christine christine 0 May 21 13:44 fell
294561 -rw-rw-r-- 1 christine christine 0 May 21 13:44 fill
296742 -rw-rw-r-- 1 christine christine 0 May 21 13:44 full
296730 -rw-rw-r-- 1 christine christine 0 May 21 13:44 fzll
$
注意,移动文件会将文件名从fall更改为fzll,但inode编号和时间戳保持不变。这是因为mv只影响文件名。
也可以使用mv来移动文件的位置。
$ ls -li /home/christine/fzll
296730 -rw-rw-r-- 1 christine christine 0 May 21 13:44
/home/christine/fzll
$
$ ls -li /home/christine/Pictures/
total 0
$ mv fzll Pictures/
$
$ ls -li /home/christine/Pictures/
total 0
296730 -rw-rw-r-- 1 christine christine 0 May 21 13:44 fzll
$
$ ls -li /home/christine/fzll
ls: cannot access /home/christine/fzll: No such file or directory
$
在上例中,我们使用mv命令把文件fzll从/home/christine移动到了/home/christine/Pirctures。和刚才一样,这个操作并没有改变文件的inode编号或时间戳。
和cp命令类似,也可以在mv命令中使用-i参数。这样在命令试图覆盖已有的文件时,你就会得到提示。
唯一变化的就是文件的位置。/home/christine目录下不再有文件fzll,因为它已经离开了原先的位置,这就是mv命令所做的事情。
也可以使用mv命令移动文件位置并修改文件名称,这些操作只需一步就能完成。
$ ls -li Pictures/fzll
296730 -rw-rw-r-- 1 christine christine 0 May 21 13:44
Pictures/fzll
$
$ mv /home/christine/Pictures/fzll /home/christine/fall
$
$ ls -li /home/christine/fall
296730 -rw-rw-r-- 1 christine christine 0 May 21 13:44
/home/christine/fall
$
$ ls -li /home/christine/Pictures/fzll
ls: cannot access /home/christine/Pictures/fzll:
No such file or directory
在这个例子中,我们将文件fzll从子目录Pictures中移动到了主目录/home/christine,并将名字改为fall。文件的时间戳和inode编号都没有改变。改变的只有位置和名称。
也可以使用mv命令移动整个目录及其内容。
$ ls -li Mod_Scripts
total 26
296886 -rwxrw-r-- 1 christine christine 929 May 21 16:16
file_mod.sh
296887 -rwxrw-r-- 1 christine christine 54 May 21 16:27
my_script
296885 -rwxrw-r-- 1 christine christine 254 May 21 16:16
SGID_search.sh
296884 -rwxrw-r-- 1 christine christine 243 May 21 16:16
SUID_search.sh
$
$ mv Mod_Scripts Old_Scripts
$
$ ls -li Mod_Scripts
ls: cannot access Mod_Scripts: No such file or directory
$
$ ls -li Old_Scripts
total 26
296886 -rwxrw-r-- 1 christine christine 929 May 21 16:16
file_mod.sh
296887 -rwxrw-r-- 1 christine christine 54 May 21 16:27
my_script
296885 -rwxrw-r-- 1 christine christine 254 May 21 16:16
SGID_search.sh
296884 -rwxrw-r-- 1 christine christine 243 May 21 16:16
SUID_search.sh
$
目录内容没有变化。只有目录名发生了改变。
在知道了如何使用mv命令进行重命名……不对……移动文件之后,你应该发现这其实非常容易的。另一个简单但可能有危险的任务是删除文件
迟早有一天,你得删除已有的文件。不管是清理文件系统还是删除某个软件包,总有要删除文件的时候。
在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参数的好习惯。
也可以使用通配符删除成组的文件。别忘了使用-i选项保护好自己的文件。
$ rm -i f?ll
rm: remove regular empty file 'fell'? y
rm: remove regular empty file 'fill'? y
rm: remove regular empty file 'full'? y
$
$ ls -l f?ll
ls: cannot access f?ll: No such file or directory
$
rm命令的另外一个特性是,如果要删除很多文件且不受提示符的打扰,可以用-f参数强制删除。小心为妙!