第5章 Linux文件及目錄管理命令基礎

第5章 Linux文件及目錄管理命令基礎

5.1 操作Linux必知必會基礎知識

在企業裏,絕大多數使用Linux的管理員都是通過命令行來操作Linux的,學會如何通過命令行操作Linux是一個Linux管理員重要的必修課。

5.1.1 Linux命令行組成結構

登錄或連接Linux之後,會進入到如下命令行狀態:


[[email protected] ~]#

表5-1裏針對上述命令行字符的組成給出了各自的含義。

表5-1 命令行字符的含義

提示:第4章中已經簡單講解過命令行的組成知識,若有不清楚的地方,讀者可以返回第4章查閱,此處不再贅述。

5.1.2 基本的Linux命令操作語法示例

在操作Linux命令之前,先看下命令操作語法格式圖,如圖5-1所示。

圖5-1 Linux命令操作語法格式圖

在Linux系統運維工作中,常用的操作大多都是在命令行下實現的,示例如下:


[[email protected] ~]#  #<==就是在這樣的提示符下輸入命令。

Linux系統命令操作語法的格式具體如下:


命令 [參數選項]  [文件或路徑]
rm   -f          /etc/hosts

說明:

1)中括號[]表示可選,即命令的參數及路徑文件是可選的。

2)參數選項表示使用一個命令的不同功能。

3)命令、參數選項、文件或路徑兩兩之間至少要有一個空格。

操作示例:創建一個test文件,然後查看創建結果,最後刪除它,再查看刪除結果。代碼如下:


[[email protected] ~]# touch test.txt #<==創建一個test.txt文件。
[[email protected] ~]# ls #<==查看創建結果。
anaconda-ks.cfg  install.log  install.log.syslog  test.txt #<==結尾帶底紋的就是。
[[email protected] ~]# rm -f test.txt #<==刪除text.txt。
[[email protected] ~]# ls #<==查看刪除結果。
anaconda-ks.cfg  install.log  install.log.syslog #<==test.txt已經沒了。

上述代碼段中的這一組操作涉及了Linux的三個基本命令:touch(創建文件)、ls(查看目錄下的內容)和rm(刪除文件或目錄)。怎麼樣?Linux還是很有趣的吧,當你熟練之後你會發現,這樣的操作效率遠比Windows下高很多,比如批量創建1萬個文件的時候。

表5-2通過現實生活中的一個比喻讓讀者對命令的語法構成印象更加深刻。

表5-2 Linux命令語法格式的形象比喻

5.1.3 Linux與Windows的目錄結構對比

大家都熟悉Windows以及Windows的目錄結構,圖5-2是Linux與Windows的目錄結構對比圖,該圖可以幫助讀者快速理解Linux系統的目錄結構,更多的目錄知識將在第6章詳細講解。

圖5-2 Linux與Windows目錄結構對比

小結一下,Windows的目錄形式爲c:\windows\,當然還有d盤、e盤的目錄結構,路徑分隔符是「\」(撬棍,反斜線),Linux的目錄形式爲/etc/hosts,路徑分割符爲「/」(斜線),Linux系統一切目錄的起點都是從「/」根開始。

5.2 Linux文件及目錄核心命令

操作Linux命令行,最基本的對象就是目錄和文件,因此本節開始爲大家講解一些基礎且核心的操作Linux的基本命令,讀者需要重點掌握。

5.2.1 pwd:顯示當前所在位置的信息

【命令星級】  ★★★★★

【功能說明】

pwd命令是「print working directory」中每個單詞的首字母縮寫,其功能是顯示當前工作目錄的絕對路徑。在實際工作中,我們在命令行操作命令時,經常會在各個目錄路徑間進行切換,此時可使用pwd命令快速查看當前所在的目錄路徑。

【語法格式】


pwd  [option]
pwd  [選項] 

說明:

1)注意pwd命令與後面的選項之間至少要有一個空格。

2)通常情況下,執行pwd命令不需要附帶任何參數。

【選項說明】

表5-3針對pwd的參數選項進行了說明。

表5-3 pwd命令的參數選項及說明

查看命令幫助時,我們經常會看到「-L,--logical」這樣的選項格式,這種寫法的意思是「-L」和「--logical」的功能是一樣的,在使用選項時,只需要選擇一種即可,但不能同時使用,而我們最常用的就是簡寫的「-L」這種格式。

此外,在表5-3中提到的PWD系統環境變量,可以利用「$」符號輸出其值,示例代碼如下:


[[email protected] ~]# echo $PWD  #<==echo命令能夠輸出指定變量,具體用法見echo命令。
/root
[[email protected] ~]# pwd -L     #<==顯示邏輯(忽略軟鏈接文件)路徑。
/root

也就是說,pwd-L和echo$PWD二者的功能是等價的。

【應用範例】

範例5-1:不帶任何選項執行pwd命令。


[[email protected] ~]# pwd             #<==不帶任何選項執行pwd命令。
/root                             #<==輸出的目錄路徑爲當前用戶root的家目錄。
[[email protected] ~]# cd /etc/init.d/  #<==進入/etc/init.d/目錄,cd命令的具體用法請參
                              見本書5.2.2節cd命令的講解。
[[email protected] init.d]# pwd
/etc/init.d                     #<==此時用戶所在的路徑爲/etc/init.d目錄。

範例5-2:對比使用-L和-P參數(瞭解即可)。


[[email protected] init.d]# ll /etc/init.d #<==ls命令的具體用法請參見本書ls命令。
lrwxrwxrwx. 1 root root 11 Jan 29 20:29 /etc/init.d -> rc.d/init.d
#<==/etc/init.d是/etc/rc.d/init.d目錄的軟鏈接,相當於快捷方式。後面在講解ln命令時
    (8.2.3節)會講解此知識。
[[email protected] init.d]# pwd -L     #<==獲取環境變量的PWD對應的值,即爲echo $PWD的結果。
/etc/init.d
[[email protected] init.d]# echo $PWD  #<==輸出環境變量PWD對應的值。
/etc/init.d
[[email protected] init.d]# pwd -P     #<==顯示鏈接對應的源文件的目錄路徑。
/etc/rc.d/init.d 

範例5-3:在Bash命令行顯示當前用戶的完整路徑。

系統Bash命令行的提示符是由一個叫作PS1的系統環境變量控制的。PS1對應的知識見表5-4。

表5-4 PS1變量對應知識列表

因此,要想查看當前PS1變量的值,可採用如下命令:


[[email protected] ~]# echo $PS1  #<==打印超級管理員對應的PS1值。
[\[email protected]\h \W]\$                #<== @是一個分隔符,與郵箱地址中的@作用類似。

可修改PS1變量對應的值,並讓命令行顯示全路徑:


[[email protected] ~]# PS1='[\[email protected]\h \w]\$ '  #<==將默認的\W改爲\w(小寫w),此命令僅臨時生效。
[[email protected] ~]# cd /etc/sysconfig    #<==切換目錄實驗。
[[email protected] /etc/sysconfig]#         #<==可以看到此處的路徑就是全路徑了。

上面的方法只是臨時性的,若要讓PS1變量永久生效,可採用如下配置方法。

編輯/etc/bashrc文件,找到符合下面內容的一行(大約在第36行),將內容中大寫的W改爲小寫的w,即可讓變量永久生效。也就是將:


[ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\[email protected]\h \W]\\$ "

改爲下面的內容,保存並退出/etc/bashrc文件:


[ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\[email protected]\h \w]\\$ "

更漂亮美觀的命令行PS1變量設置參數如下:


PS1="[\[\e[34;1m\]\[email protected]\[\e[0m\]\[\e[32;1m\]\H\[\e[0m\]\[\e[31;1m\] \w\[\e[0m\]]\\$"

最後,註銷重新登錄系統或直接執行source/etc/bashrc使得修改的信息生效,有關Linux終端提示符還有很多有用又好玩的技巧呢!感興趣的讀者可以瀏覽老男孩博客的相關文章,地址爲http://blog.oldboyedu.com/command-line-terminal/。

5.2.2 cd:切換目錄

【命令星級】  ★★★★★

【功能說明】

cd命令是「changedirectory」中每個單詞的首字母縮寫,其功能是從當前工作目錄切換到指定的工作目錄。

【語法格式】


cd  [option]  [dir] 
cd  [選項]    [目錄]

說明:

1)注意cd命令以及後面的選項和目錄,每個元素之間都至少要有一個空格。

2)cd命令後面的選項和目錄等參數都可以省略。默認情況下,單獨執行cd命令,可切換到當前登錄用戶的家目錄(由系統環境變量HOME進行定義)。

3)cd是bash shell的內置命令,查看該命令對應的系統幫助需要使用help cd。

【選項說明】

表5-5針對cd命令的參數選項進行了說明。

表5-5 cd命令的參數選項及說明

對於cd命令,筆者有一些實踐經驗分享如下。

·在使用cd命令時,如果使用鍵盤上「Tab」鍵的自動補齊功能,則可以提高輸入速度和準確度。這個「Tab」鍵的自動補齊功能同樣也適用於其他命令。

·需要了解一下路徑的概念,比如,相對路徑不是從「/」斜線開始的路徑,而是從當前目錄或指定的目錄開始的,例如,data/,mnt/oldboy;絕對路徑是從「/」斜線根開始的路徑,例如,/data/、/mnt/oldboy。

·當需要切換到當前用戶上一次所在的目錄時,請使用「cd-」(注意中間的空格);當需要切換到當前用戶的家目錄時,請使用「cd~」(注意中間的空格);當需要切換到當前目錄的上一級目錄所在的路徑時,請使用「cd..」(注意中間的空格)。

【實踐範例】

範例5-4:進入系統/etc目錄(cd/etc)。


[[email protected] ~]# pwd
/root #<==在Linux系統中每個用戶都有自己的家目錄,默認情況下,用戶登錄系統後會進入自己的
       家目錄。root用戶的家目錄是/root,普通用戶的家目錄默認是/home/用戶名/。
[[email protected] ~]# cd /usr/local/     #<==切換到/usr/local/目錄。
[[email protected] local]# pwd
/usr/local                       #<==此時已經進入/usr/local目錄了。

範例5-5:切換到當前目錄的上一級目錄(cd..)。


[[email protected] local]# pwd
/usr/local
[[email protected] local]# cd .. #<==「..」等同於上一級目錄名,也可以寫成「../」。
[[email protected] usr]# pwd
/usr                       #<==此時切換到了/usr目錄。

範例5-6:進入當前目錄的父目錄的父目錄(cd../../)中。


[[email protected] usr]# cd /usr/local/
[[email protected] local]# pwd
/usr/local
[[email protected] local]# cd ../../  #<==退到當前目錄的上兩級目錄,即退到「/」目錄。
[[email protected] /]# pwd
/

提示:只要目錄具有足夠多的層次,則可一直這樣繼續下去「cd../../../..」,直到退到「/」爲止。

範例5-7:返回當前用戶上一次所在的目錄(cd-)。


[[email protected] /]# cd /usr/local/
[[email protected] local]# pwd
/usr/local
[[email protected] local]# cd   #<==cd命令不接任何參數時,從環境變量HOME獲取路徑名,即切換
                                到當前用戶的家目錄。
[[email protected] ~]# pwd      #<==當前用戶的工作路徑爲/root。
/root
[[email protected] ~]# cd -     #<==執行「cd -」時,cd將從環境變量OLDPWD對應值獲取路徑名,
/usr/local                #<==即切換到了當前用戶上一次的工作路徑「/usr/local」。

範例5-8:進入當前用戶的家目錄(cd~)。


[[email protected] /]# cd /usr/local/
[[email protected] local]# pwd
/usr/local
[[email protected] local]# cd ~       #<==「~」即鍵盤左上角Esc鍵下方的波浪符號,其代表家目錄。
[[email protected] ~]# pwd
/root                       #<==切換到當前用戶的家目錄。

提示:執行不帶任何參數的cd命令與「cd~」的結果一樣。

5.2.3 tree:以樹形結構顯示目錄下的內容

【命令星級】  ★★★★☆

【功能說明】

tree命令的中文意思爲「樹」,功能是以樹形結構列出指定目錄下的所有內容,包括所有文件、子目錄及子目錄裏的目錄和文件。

【語法格式】


tree  [option]  [directory]
tree  [選項]     [目錄] 

說明:

1)注意tree命令以及後面的選項和目錄,每個元素之間都至少要有一個空格。

2)若tree命令後不接選項和目錄,則默認顯示當前所在路徑目錄的目錄結構。

【選項說明】

表5-6針對tree命令的參數選項進行了說明。

表5-6 tree命令的參數選項及說明

【應用範例】

在講解範例之前,先做一些準備工作,步驟如下。

第一步,安裝tree命令。

首先檢查系統是否安裝了tree命令,如果採用的是最小化安裝Linux系統的方式,那麼tree命令有可能並沒有安裝。此時可用yum命令安裝tree命令:


[[email protected] ~]# rpm -qa tree        #<==查詢tree命令是否安裝。
tree-1.5.3-2.el6.x86_64                 #<==如果沒有顯示就執行下面的命令。
[[email protected] ~]# yum -y install tree #<==安裝tree命令的yum命令,本書開頭已帶讀者
                                安裝過了。

第二步,調整系統字符集,防止樹形結構顯示亂碼。

在使用樹形結構時,很可能會因爲字符集而導致出現亂碼問題,比如導致樹形的樹枝部分都是問號,例如,下面的命令可做爲臨時解決樹結構亂碼的方法:


[[email protected] ~]# LANG=en_US.UTF-8

這個問題與Linux系統字符集以及我們連接Linux的客戶端的字符集都有關聯。

範例5-9:不帶任何參數執行tree命令。


[[email protected] etc]# cd ~
[[email protected] ~]# tree       #<==顯示當前目錄結構。
.      #<==「.」以當前目錄爲起點。
└── anaconda-ks.cfg
0 directories, 1 file

範例5-10:以樹形結構顯示目錄下的所有內容(-a的功能)。


[[email protected] ~]# tree -a #<==帶-a參數顯示所有文件(包括隱藏文件)。
.
├── anaconda-ks.cfg
├── .bash_history     #<==在Linux系統中,以「.」(點號)開頭的文件爲隱藏文件,默認不顯示。
├── .bash_logout
├── .bash_profile
...省略若干行...
└── .viminfo
0 directories, 9 files

範例5-11:只列出根目錄下第一層的目錄結構(-L功能)。


[[email protected] ~]# tree -L 1 /      #<==-L參數後接數字,表示查看目錄的層數,若不帶-L
                       選項則默認顯示所有層數。
/
├── bin -> usr/bin
├── boot
├── dev
...省略若干行...
├── media
├── mnt
├── opt
...省略若干行...
└── var
19 directories, 0 files

範例5-12:只顯示所有的目錄(但不顯示文件)。


[[email protected] ~]# tree -d /boot   #<==-d參數表示只顯示目錄。
/boot
├── efi
│   └── EFI
│       └── centos
├── grub
└── grub2
    ├── fonts
    ├── i386-pc
    └── locale
8 directories
[[email protected] ~]# tree -dL 1 /boot #<==-d參數只顯示目錄,-L參數表示顯示層數,這裏是1層。
/boot
├── efi
├── grub
└── grub2
3 directories

範例5-13:使用tree命令區分目錄和文件的方法(使用-F和-d參數)。


[[email protected] ~]# tree -L 1 -F /boot/  #<==使用-F參數會在目錄後面添加「/」,以方便區分
                                目錄。
/boot/
├── config-3.10.0-957.1.3.el7.x86_64
├── config-3.10.0-957.el7.x86_64
├── efi/      #<==結尾帶斜線的就是目錄。
├── grub/
├── grub2/
├── initramfs-0-rescue-040ea756a4d344249aec0555d4c01569.img
├── initramfs-3.10.0-957.1.3.el7.x86_64.img
...省略若干行...
└── vmlinuz-3.10.0-957.el7.x86_64*
3 directories, 12 files
[[email protected] ~]# tree -L 1 -F /boot/|grep /$   #<==過濾以斜線結尾的所有內容,如果大家
                              暫時還看不懂這個方法,可以等學完grep
                              命令後再回看。
/boot/
├── efi/
├── grub/
├── grub2/
[[email protected] ~]# tree -L 1 -d /boot/   #<==使用-d參數只顯示目錄樹,輕鬆過濾內容中的目錄。
/boot/
|-- efi
|-- grub
`-- lost+found
3 directories

5.2.4 mkdir:創建目錄

【命令星級】  ★★★★★

【功能說明】

mkdir命令是由「makedirectories」中每個單詞的粗體字母組合而成,其功能是創建目錄,默認情況下,如果要創建的目錄已經存在,則會提示文件存在,而不會繼續創建目錄。

【語法格式】


mkdir  [option]  [directory] #<==注意mkdir命令以及後面的選項和目錄之間都至少要有一
                                 個空格。
mkdir  [選項]    [目錄 ]     #<== mkdir命令可以同時創建多個目錄,格式爲mkdir dir1
                                 dir2 …

【選項說明】

表5-7針對mkdir命令的參數選項進行了說明。

表5-7 mkdir命令的參數選項及說明

【應用範例】

範例5-14:不使用任何命令參數創建目錄的用法示例。

我們先查看下當前目錄樹的結構,命令如下:


[[email protected] ~] # cd ~
[[email protected] ~] # tree -d 
.               #<==根據結果可以看出當前目錄下沒有任何目錄。
0 directories

開始測試創建目錄,並檢查,命令如下:


[[email protected] ~]# mkdir data     #<==在當前目錄下創建data目錄,此處的data是相對路徑。
[[email protected] ~]# tree -d
.
└── data     #<==可以看到data目錄已經創建。
1 directory
[[email protected] ~]# mkdir data     #<==再次執行創建命令會提示目錄已經存在。
mkdir: cannot create directory `data': File exists 

擴展知識:

Windows下的目錄路徑樣式爲D:\data\test,而Linux下的路徑樣式爲/data/test,它們的目錄頂點和分隔符均不相同。

範例5-15:使用-p參數遞歸創建目錄。

當我們創建多級目錄時,如果第一級目錄(oldboy)不存在,則創建結果會報錯,導致無法成功創建,操作如下:


[[email protected] ~]# mkdir oldboy/test
mkdir: cannot create directory `oldboy/test': No such file or directory 
    #<==提示沒有這個文件或目錄。

此時,可以指定-p參數遞歸創建多級目錄,命令如下:


[[email protected] ~]# mkdir -p oldboy/test
[[email protected] ~]# tree -d
.
├── data
└── oldboy   #<==同時創建了oldboy目錄及oldboy下的子目錄test。
    └── test
3 directories

使用mkdir創建多級目錄時,建議直接使用-p參數,可以避免出現「No such file or directory」這樣沒有文件或目錄的報錯了,且不會影響已存在的目錄。

範例5-16:加-v參數顯示創建目錄的過程。

使用-v參數顯示創建目錄的詳細過程,具體操作命令如下:


[[email protected] ~]# mkdir -pv oldboy2/test
mkdir: created directory `oldboy2'
mkdir: created directory `oldboy2/test'

提示:其實這個-v並無實際用途。

範例5-17:創建目錄時可使用-m參數設置目錄的默認權限。


[[email protected] ~]# mkdir dir1
[[email protected] ~]# ls -ld dir1                   #<== ls命令的使用方法詳見後面的
                                                    5.2.6節ls命令的相關內容。
drwxr-xr-x 2 root root 4096 Nov  5 18:21 dir1  #<==創建該目錄的默認權限爲755。
[[email protected] ~]# mkdir -m 333 dir2             #<==創建目錄時指定333的數字權限。
[[email protected] ~]# ls -ld dir2
d-wx-wx-wx 2 root root 4096 Nov  5 18:21 dir2  #<==可以看到權限已經發生了變化。

提示:有關權限的知識可參考後文講解的chmod命令。

5.2.5 touch:創建文件或更改文件時間戳

【命令星級】  ★★★★★

【功能說明】

touch命令包含兩個功能:一是創建新的空文件;二是改變已有文件的時間戳屬性。

【語法格式】


touch  [option]  [file]
touch  [選項]     [文件] 

說明:

1)touch命令以及後面的選項和文件,每個元素之間都至少要有一個空格。

2)注意區分touch和mkdir命令的功能,mkdir命令是創建空目錄,而touch是創建空文件。

3)在Linux中,一切皆文件。雖然touch命令不能創建目錄,但是可以修改目錄的時間戳。

【選項說明】

表5-8針對touch命令的參數選項進行了說明。

表5-8 touch命令的參數選項及說明

【應用範例】

範例5-18:創建文件示例(用於文件事先不存在的情況)。


[[email protected] ~]# mkdir /test          #<==在根下新建一個test目錄。
[[email protected] ~]# cd /test/            #<==切換到/test目錄。
[[email protected] test]# touch oldboy.txt  #<==創建空文件oldboy.txt。
[[email protected] test]# ls                  #<==可以看到oldboy.txt文件創建成功。
oldboy.txt
[[email protected] test]# touch a.txt b.txt  #<==同時創建多個文件,類似於mkdir創建多個目錄。
[[email protected] test]# ls
a.txt  b.txt  oldboy.txt
[[email protected] test]# touch stu{01..05} #<==可以利用大括號「{}」輸出的字符序列批量創建
                                          文件。
[[email protected] test]# ls
a.txt  b.txt  oldboy.txt  stu01  stu02  stu03  stu04  stu05

範例5-19:更改文件的時間戳屬性。


[[email protected] ~]# stat oldboy.txt #<==stat命令可以查看文件的時間戳屬性,具體用法見stat
                                     命令的講解。
  File: `oldboy.txt'
  Size: 0               Blocks: 0          IO Block: 4096   regular empty file
Device: 802h/2050d      Inode: 272247      Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2015-07-30 17:37:32.295105308 +0800
Modify: 2015-07-30 17:37:32.295105308 +0800
Change: 2015-07-30 17:37:32.295105308 +0800
#<==說明:文件的時間戳屬性分爲訪問時間、修改時間和狀態改變時間。
[[email protected] ~]# touch -a oldboy.txt #<==-a參數可用於更改最後的訪問時間。
[[email protected] ~]# stat oldboy.txt
  File: `oldboy.txt'
  Size: 0               Blocks: 0          IO Block: 4096   regular empty file
Device: 802h/2050d      Inode: 272247      Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2015-07-30 17:48:20.502156890 +0800
Modify: 2015-07-30 17:37:32.295105308 +0800
Change: 2015-07-30 17:48:20.502156890 +0800
[[email protected] ~]# touch -m oldboy.txt  #<==-m參數用於更改最後的修改時間。
[[email protected] ~]# stat oldboy.txt 
  File: `oldboy.txt
  Size: 0               Blocks: 0          IO Block: 4096   regular empty file
Device: 802h/2050d      Inode: 272247      Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2015-07-30 17:48:20.502156890 +0800
Modify: 2015-07-30 17:48:45.006106223 +0800
Change: 2015-07-30 17:48:45.006106223 +0800

範例5-20:指定時間屬性創建/修改文件。

可利用選項-d指定創建文件後的文件修改時間,示例代碼如下:


[[email protected] ~]# ls -lh oldboy.txt
-rw-r--r-- 1 root root 0 Oct 23 20:20 oldboy.txt #<==修改前的文件修改時間是10月23日。
[[email protected] ~]# touch -d 20201001 oldboy.txt    #<==指定創建文件後的文件修改時間爲2020
                                                     年10月01日。
[[email protected] ~]# ls -lh oldboy.txt
-rw-r--r-- 1 root root 0 Oct  1  2020 oldboy.txt #<==文件修改時間已改爲2020年10月01日。

也可利用選項-r,修改oldboy.txt的時間屬性,使其與a.txt的時間屬性一致,示例代碼如下:


[[email protected] ~]# ls -lh a.txt 
-rw-r--r-- 1 root root 0 Oct 23 20:20 a.txt    #<==查看a.txt的修改時間。
[[email protected] ~]# touch -r a.txt oldboy.txt     #<==使用-r參數使得oldboy.txt時間
                                  屬性與a.txt一致。
[[email protected] ~]# ls -lh oldboy.txt
-rw-r--r-- 1 root root 0 Oct 23 20:20 oldboy.txt   #<==oldboy.txt文件的修改時間
                                 已與a.txt一致了。

還可以利用選項-t,將文件設置爲201512312234.50的時間格式,示例代碼如下:


[[email protected] ~]# touch -t 201512312234.50 oldboy.txt
[[email protected] ~]# ls -lh --full-time oldboy.txt
-rw-r--r-- 1 root root 0 2015-12-31 22:34:50.000000000 +0800 oldboy.txt
    #<==查看設置的屬性。

上述案例涉及的ls命令的用法詳見後面5.2.6節ls的相關內容講解。

【擴展知識】

這裏擴展一點有關時間戳屬性的知識。

GNU/Linux的文件共包含3種類型的時間戳:


Access: 2015-07-30 17:48:20.502156890 +0800    #<==文件最後被訪問的時間。
Modify: 2015-07-30 17:48:45.006106223 +0800    #<==文件最後被修改的時間。
Change: 2015-07-30 17:48:45.006106223 +0800    #<==文件狀態最後被改變的時間。

對應ls命令,查看上述時間戳的選項如下:


mtime: 最後修改時間(ls -lt) #<==修改文件內容,文件的修改時間(modify time)會改變。
ctime: 狀態改變時間(ls -lc) #<==修改文件內容、移動文件或改變文件屬性等,文件的change
                  時間會改變。
atime: 最後訪問時間(ls -lu) #<==查看文件內容時,文件的訪問時間(access time)會改變。

5.2.6 ls:顯示目錄下內容及屬性信息的命令

【命令星級】  ★★★★★

【功能說明】

ls命令可以理解爲英文單詞List的縮寫,其功能是列出目錄的內容及其內容屬性信息(list directory contents)。該命令有點類似於DOS系統下的dir命令,有趣的是Linux下其實也有dir命令,但我們更習慣使用ls。

【語法格式】


ls  [option]  [file]
ls  [選項]     [<文件或目錄>] 

說明:

1)ls命令以及後面的選項和文件,每個元素之間都至少要有一個空格。

2)命令後面的選項和目錄文件可以省略,表示查看當前路徑的文件信息。

【選項說明】

表5-9針對ls命令的參數選項進行了說明。

表5-9 ls命令的參數選項及說明

【應用範例】

在開始範例講解之前,先做一些準備,順便整合一下使用前面的命令。準備代碼如下:


[[email protected] ~]# mkdir /test  #<==在根「/」下創建一個目錄test。
[[email protected] ~]# cd /test/    #<==切換到/test目錄下。
[[email protected] test]# touch file1.txt file2.txt file3.txt #<==批量創建若干文件。
[[email protected] test]# mkdir dir1 dir2 dir3 #<==批量創建多個目錄,每個目標目錄名兩端要
                            有空格。
[[email protected] test]# tree                 #<==顯示前面創建的文件及目錄結構。
.
├── dir1
├── dir2
├── dir3
├── file1.txt
├── file2.txt
└── file3.txt
3 directories, 3 files 

範例5-21:直接執行ls命令,不帶任何參數。


[[email protected] test]# ls  #<==不加參數的結果,顯示所有文件和目錄
dir1  dir2  dir3  file1.txt  file2.txt  file3.txt

範例5-22:使用-a參數顯示所有文件,特別是隱藏文件。


[[email protected] test]# touch .file4.txt #<==再創建一個隱藏文件,在Linux系統中以「.」
                         (點號)開頭的文件就是隱藏文件。
[[email protected] test]# ls
dir1  dir2  dir3  file1.txt  file2.txt  file3.txt
[[email protected] test]# ls -a
.  ..  dir1  dir2  dir3  file1.txt  file2.txt  file3.txt  .file4.txt
#<==說明:加了-a參數,就會把以「.」(點號)開頭的內容顯示出來。這裏顯示的第一個點號,表示當前目錄,即test目錄本身,而兩個點號表示當前目錄的上級目錄,此處就是代表根目錄。有關一個點、兩個點的知識,在8.2.3節的ln命令中會有詳細講解。
[[email protected] test]# ls -A #<==列出所有文件,包括隱藏文件,但不包括「.」與「..」這兩個目錄。
dir1  dir2  dir3  file1.txt  file2.txt  file3.txt  .file4.txt

範例5-23:使用-l參數顯示詳細信息。


[[email protected] test]# ls -l  #<==此處時間屬性列默認顯示的是文件的最後一次修改時間。
total 12
drwxr-xr-x 2 root root 4096 Oct 25 11:13 dir1
drwxr-xr-x 2 root root 4096 Oct 25 11:13 dir2
drwxr-xr-x 2 root root 4096 Oct 25 11:13 dir3
-rw-r--r-- 1 root root    0 Oct 25 11:13 file1.txt
-rw-r--r-- 1 root root    0 Oct 25 11:13 file2.txt
-rw-r--r-- 1 root root    0 Oct 25 11:13 file3.txt
#<==說明:這個「-l」參數是最常用的參數,意思是用長格式列出目錄下的文件類型、權限,連接數、屬主(組)及創建修改時間的信息。這裏的每個列的屬性含義都需要熟練掌握,後文會詳細討論這些屬性信息。

可能有人已經注意到了,創建或修改時間的格式沒有年份的信息,那麼如何顯示時間的全部信息呢?見範例5-24。

範例5-24:顯示完整時間屬性的參數--time-style=long-iso。


[[email protected] test]# ls -l --time-style=long-iso   #<==以long-iso方式顯示時間,
                                 這個命令結果是非常棒的。
total 12
drwxr-xr-x 2 root root 4096 2015-10-25 11:13 dir1
drwxr-xr-x 2 root root 4096 2015-10-25 11:13 dir2
drwxr-xr-x 2 root root 4096 2015-10-25 11:13 dir3
-rw-r--r-- 1 root root    0 2015-10-25 11:13 file1.txt
-rw-r--r-- 1 root root    0 2015-10-25 11:13 file2.txt
-rw-r--r-- 1 root root    0 2015-10-25 11:13 file3.txt
#<==提示:這樣的時間格式是不是看起來總是讓人心情舒暢呢?--time-style的其他可選參數請大家自行測試。

對於上面的命令,說明如下。

1)--time-style包含的可選參數值有:full-iso、long-iso、iso、locale。默認值是locale。

2)在生產場景中經常會遇到同一目錄下文件及目錄時間的顯示不一致的問題,所以需要用ls-l--time-style=long-iso來進行調整,如果覺得參數太多不好記,則可以設置一個別名來進行管理,詳見後文的alias命令。

3)值得一提的是,執行ls-l等命令時,默認顯示的是文件最後一次修改的時間(如果是新文件就是創建時間)。

4)ls--full-time用於顯示完整的時間,等同於ls-l--time-style=full-iso。

既然ls-l輸出結果的時間屬性列爲修改時間,那麼能否改成其他的時間呢?例如,顯示最後一次文件訪問的時間。這當然是可以的,見下文。

範例5-25:執行ls命令,帶顯示內容的訪問時間屬性的參數。


[[email protected] test]# stat file1.txt  #<==顯示文件的屬性及狀態信息,stat命令後文會詳細
                                        講解,暫時不用理會。
  File: `file1.txt'
  Size: 0               Blocks: 0         IO Block: 4096   regular empty file
Device: 802h/2050d      Inode: 271005     Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/   root)   Gid: (    0/    root)
Access: 2015-10-25 11:13:38.875401372 +0800 #<==這裏就是文件的訪問時間,是我們現在
                                                需要關注的。
Modify: 2015-10-25 11:13:38.875401372 +0800
Change: 2015-10-25 11:13:38.875401372 +0800 
[[email protected] test]# date #<==查看當前的系統時間。
Sun Oct 25 19:44:00 CST 2015 
[[email protected] test]# cat file1.txt   #<==查看文件內容即表示訪問文件了,cat命令後面會講,
                                       暫時不用理會。
[[email protected] test]# stat file1.txt  #<==重新查看文件的訪問時間。
  File: `file1.txt'
  Size: 0               Blocks: 0          IO Block: 4096   regular empty file
Device: 802h/2050d      Inode: 271005      Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2015-10-25 19:44:22.033071250 +0800 #<==我們發現file1.txt的訪問時間已經
                                                 發生了變化。
Modify: 2015-10-25 11:13:38.875401372 +0800
Change: 2015-10-25 11:13:38.875401372 +0800
[[email protected] test]# ls -l --time-style=long-iso --time=atime 
    #<==增加--time=atime參數,顯示訪問時間。
total 12
drwxr-xr-x 2 root root 4096 2015-10-25 11:13 dir1
drwxr-xr-x 2 root root 4096 2015-10-25 11:13 dir2
drwxr-xr-x 2 root root 4096 2015-10-25 11:13 dir3
-rw-r--r-- 1 root root    0 2015-10-25 19:44 file1.txt #<==文件的時間列確實發生了變化,
                                  是前面的訪問時間無疑。
-rw-r--r-- 1 root root    0 2015-10-25 11:13 file2.txt
-rw-r--r-- 1 root root    0 2015-10-25 11:13 file3.txt
[[email protected] test]# ls -l --time-style=long-iso
total 12
drwxr-xr-x 2 root root 4096 2015-10-25 11:13 dir1
drwxr-xr-x 2 root root 4096 2015-10-25 11:13 dir2
drwxr-xr-x 2 root root 4096 2015-10-25 11:13 dir3
-rw-r--r-- 1 root root    0 2015-10-25 11:13 file1.txt #<==這裏是文件的默認修改
                                                            時間列。
-rw-r--r-- 1 root root    0 2015-10-25 11:13 file2.txt
-rw-r--r-- 1 root root    0 2015-10-25 11:13 file3.txt
#<==通過以上實踐,我們可以得出結論了。--time=atime顯示的確實是訪問時間,而非默認的修改時間。

對於上面的命令,說明如下。

1)與之相關的命令還有ls-l--time-style=long-iso--time=ctime,用於顯示文件的改變時間。

2)有關文件時間列及mtime、atime、ctime的知識,前文在介紹touch命令時已經講解過了。

範例5-26:執行ls命令,帶-F參數(有些類似於tree命令的-F)。


[[email protected] test]# ls -F
dir1/  dir2/  dir3/  file1.txt  file2.txt  file3.txt
#<==說明:加了-F之後,我們可以清晰地看到所有目錄的結尾都加上了斜線/。這樣的功能對於工作有什麼用呢?當然有用了,例如,我們要過濾出所有的目錄來,那麼只需要將帶斜線的過濾出來就可以了。
[[email protected] test]# ls -F|grep / #<==過濾目錄,grep命令的具體用法見後面grep章節。
dir1/
dir2/
dir3/
[[email protected] test]# ls -F|grep -v /  #<==過濾普通文件。
file1.txt
file2.txt
file3.txt
#<==說明:ls的-F參數是在文件結尾加上文件類型指示符號(*、/、=、@、|,其中的一個)。

範例5-27:使用-d參數只顯示目錄本身的信息。

有時候我們想查看目錄本身的信息,但是若使用「ls目錄」命令,就會顯示目錄裏面的內容。示例代碼如下:


[[email protected] test]# ls -l dir1  #<==這樣根本無法查看dir1目錄本身的信息,除非到上級
                      目錄中查看。
total 0

如果只是想顯示目錄本身的信息,那麼這個時候參數-d就能派上用場了,示例代碼如下:


[[email protected] test]# ls -ld dir1 #<==加-d參數就可以如願以償了。
drwxr-xr-x 2 root root 4096 Oct 25 11:13 dir1

範例5-28:使用-R參數遞歸查看目錄。


[[email protected] test]# mkdir dir1/sub1/test -p  #<==遞歸創建目錄的命令。
[[email protected] test]# ls -R dir1               #<==類似於tree但沒有tree好用的方法。
dir1:
sub1

dir1/sub1:
test

dir1/sub1/test:


範例5-29:ls命令別名的相關知識及設置ls別名。

可通過如下命令查看ls在系統中的默認別名設置,執行等號前面的內容就會調用後面的命令:


[[email protected] test]# alias|grep ls  #<==alias命令的用法請參見相應的alias章節。
alias l.='ls -d .* --color=tty'
alias ll='ls -l --color=tty'
alias ls='ls --color=tty'
#<==提示:什麼是別名呢?別名很好理解,就是另外一個名字而已。

例如,顯示時間格式的參數太長,這裏就可以做個別名,示例代碼如下:


[[email protected] test]# alias lst='ls -l --time-style=long-iso' #<==配置命令別名。
[[email protected] test]# alias |grep lst                  #<==檢查命令別名是否生效。
alias lst='ls -l --time-style=long-iso'
[[email protected] test]# lst                              #<==執行命令別名,檢查效果。
total 12
drwxr-xr-x 2 root root 4096 2015-10-25 11:13 dir1
drwxr-xr-x 2 root root 4096 2015-10-25 11:13 dir2
drwxr-xr-x 2 root root 4096 2015-10-25 11:13 dir3
-rw-r--r-- 1 root root    0 2015-10-25 11:13 file1.txt
-rw-r--r-- 1 root root    0 2015-10-25 11:13 file2.txt
-rw-r--r-- 1 root root    0 2015-10-25 11:13 file3.txt
#<==注意:這裏的別名是臨時生效的,如果希望永久生效則需要將別名放到環境變量的配置裏纔可以。

範例5-30:查找最近更新過的文件。

在工作中,我們經常需要查看一個包含很多文件的目錄,找出最近更新過但不知道具體文件名的文件,這時可以用ls-lrt或者ls-rt這個組合命令,示例代碼如下:


[[email protected] test]# touch /etc/test.txt #<==創建一個新文件,假設不知道名字,你如何
                          快速找到它?
[[email protected] test]# ls -lrt /etc/       #<==-t是按時間排序,-r是倒序,即按時間倒序
                          排序。
...省略若干文件行...
-rw-r--r--  1 root root     301 May 22 10:17 mtab
drwxr-xr-x  9 root root    4096 May 22 10:22 sysconfig
-rw-r--r--  1 root root       0 May 22 20:55 test.txt
#<==不用翻屏回查,最後一屏的最後一行就是我們需要查找的文件。如果直接定位文件還可以用如下命令。
[[email protected] test]# ls -lrt /etc|tail -1  #<==tail命令後面會講。
-rw-r--r--  1 root root       0 May 22 20:55 test.txt

【ls命令輸出內容的屬性解讀】

使用ls命令之後,通常會有類似如下的輸出內容:


[[email protected] test]# ls -lhi  #<==-l參數前面已經詳細講解過了,-h參數的作用是將文件的
                    大小以人類可讀的方式顯示,像下面的4.0K你就能很容易
                    知道文件的大小,-i參數的作用是顯示文件的Inode值。
total 12K
97063 drwxr-xr-x 3 root root 4.0K May 22 20:48 dir1
97064 drwxr-xr-x 2 root root 4.0K May 22 11:51 dir2
97065 drwxr-xr-x 2 root root 4.0K May 22 11:51 dir3
97060 -rw-r--r-- 1 root root    0 May 22 11:51 file1.txt
97061 -rw-r--r-- 1 root root    0 May 22 11:51 file2.txt
97062 -rw-r--r-- 1 root root    0 May 22 11:51 file3.txt

上述命令結果中各列的含義如下。

第一列:Inode索引節點編號。

第二列:文件類型及權限(第一個字符爲類型,後9個字符爲文件權限符號)。

第三列:硬鏈接個數(詳情請參看ln命令(8.2.3節)的講解)。

第四列:文件或目錄所屬的用戶(屬主)。

第五列:文件或目錄所屬的組。

第六列:文件或目錄的大小。

第七、八、九列:文件或目錄的修改時間。

第十列:實際的文件名或目錄名。

詳細解釋見圖5-3。

【ls輸出的文件屬性舉例說明】

下面以oldboy文件爲例說明輸出文件的屬性細節(具體見表5-10),具體列的內容請參考圖5-3。


1736707 -rw-r--r-- 1  root root   35  Oct 28 11:29 oldboy

圖5-3 ls命令輸出內容的屬性解讀

表5-10 ls輸出的文件屬性細節說明

5.2.7 cp:複製文件或目錄

【命令星級】  ★★★★★

【功能說明】

cp命令可以理解爲英文單詞copy的縮寫,其功能爲複製文件或目錄。

【語法格式】


cp  [option]  [source]  [dest]
cp  [選項]    [源文件]  [目標文件]

說明:cp命令以及後面的選項和文件,每個元素之間都至少要有一個空格。

【選項說明】

表5-11針對cp命令的參數選項進行了說明。

表5-11 cp命令的參數選項及說明

【應用範例】

範例5-31:無參數和帶參數-a的比較。


[[email protected] test]# pwd
/test 
[[email protected] test]# ll -h #<==查看當前文件的時間屬性,讀者以自己的系統時間爲準。
total 12K
drwxr-xr-x 3 root root 4.0K Nov  3 20:15 dir1
drwxr-xr-x 2 root root 4.0K Nov  3 20:15 dir2
drwxr-xr-x 2 root root 4.0K Nov  3 20:15 dir3
-rw-r--r-- 1 root root    0 Nov  3 20:14 file1.txt
-rw-r--r-- 1 root root    0 Nov  3 20:14 file2.txt
-rw-r--r-- 1 root root    0 Nov  3 20:14 file3.txt
[[email protected] test]# cp file1.txt file4.txt    #<==複製file1.txt爲file4.txt。
[[email protected] test]# cp -a file1.txt file5.txt #<==使用-a參數複製file1.txt爲file5.txt。
[[email protected] test]# ll -h #<==再次查看當前文件的時間屬性。
total 12K
drwxr-xr-x 3 root root 4.0K Nov  3 20:15 dir1
drwxr-xr-x 2 root root 4.0K Nov  3 20:15 dir2
drwxr-xr-x 2 root root 4.0K Nov  3 20:15 dir3
-rw-r--r-- 1 root root    0 Nov  3 20:14 file1.txt  #<==此行是源文件。
-rw-r--r-- 1 root root    0 Nov  3 20:14 file2.txt
-rw-r--r-- 1 root root    0 Nov  3 20:14 file3.txt
-rw-r--r-- 1 root root    0 Nov  3 20:18 file4.txt  #<==此行是未使用任何參數。
-rw-r--r-- 1 root root    0 Nov  3 20:14 file5.txt  #<==此行是使用-a參數進行復制,屬性不變。

可以發現,使用-a參數進行復制時,文件的時間屬性沒有改變,-a參數的功能包含-p參數保持文件的屬性功能。

範例5-32:使用-i參數的例子


[[email protected] test]# cp -i file1.txt file5.txt #<==使用-i參數複製文件,會提示是否覆蓋文件。
cp: overwrite `file5.txt'? 
[[email protected] test]# cp file1.txt file5.txt    #<==不使用-i參數結果是一樣的,爲什麼呢?
cp: overwrite `file5.txt'?
[[email protected] test]# alias cp                 #<==原因是系統爲cp命令默認設置了別名。
alias cp='cp -i'

CentOS系統默認爲cp命令設置了別名,即增加了-i的參數。但是在Shell腳本中執行cp命令時,沒有-i參數時並不會詢問是否覆蓋。這是因爲命令行和Shell腳本執行時的環境變量不同。不過在腳本中一般使用命令的全路徑。

範例5-33:使用-r參數複製目錄。


[[email protected] test]# cp dir1 dir2/    #<==複製dir1到dir2,但結果顯示跳過目錄dir1。
cp: omitting directory `dir1'
[[email protected] test]# cp -r dir1 dir2/ #<==若使用-r參數則複製成功。 
[[email protected] test]# tree dir2        #<==查看複製結果。
dir2
└── dir1
    └── sub1
        └── test
3 directories, 0 files 
#<==提示:使用-a參數也可以達到相同的效果,因爲-a參數相當於「dpr」三個參數。

範例5-34:cp覆蓋文件不提示是否覆蓋的幾種方法。

解題思路:屏蔽系統默認的對應的命令別名。

第一種方法,使用命令全路徑,示例代碼如下:


[[email protected] test]# cp file1.txt file2.txt 
cp: overwrite `file2.txt'? y  #<==提示要輸入y以確認覆蓋,輸入n則爲不覆蓋。
[[email protected] test]# which cp  #<==查看cp的系統別名。
alias cp='cp -i'
        /bin/cp  #<==CentOS7系統裏是/usr/bin/cp,爲了兼容CentOS6,將/bin指向了/usr
                    /bin/cp。
[[email protected] test]# /bin/cp file1.txt file2.txt   #<==使用cp命令的絕對路徑,即可屏蔽別名。

第二種方法,命令開頭使用反斜線\,示例代碼如下:


[[email protected] test]# \cp file1.txt file2.txt #<==使用「\」屏蔽系統別名。
[[email protected] test]#  

第三種方法,取消cp的別名,但重啓系統失效,示例代碼如下:


[[email protected] test]# unalias cp #<==alias設置別名,unalias取消別名,具體用法見對應
                                   章節的內容詳解。
[[email protected] test]# cp file1.txt file2.txt 
[[email protected] test]#

第四種爲殺雞取卵的方法,用於開拓思路,不建議採用,示例代碼如下:


[[email protected] ~]# cat ~/.bashrc
# .bashrc
# User specific aliases and functions
alias rm='rm -i'
alias cp='cp -i' #<==編輯這個文件,註釋掉本行,重啓後生效。「.bashrc」這個文件在開機時會加載。
alias mv='mv -i'
# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

範例5-35:快速備份文件案例。

通常我們備份文件時會使用下面的格式:


[[email protected] ~]# cp /etc/ssh/sshd_config /etc/ssh/sshd_config.ori
#<==觀察上面的格式,我們可以發現有一部分路徑重複了。因此有了下面的快捷寫法,使用了「{}」的
   用法,兩種方法是等效的。
[[email protected] ~]# cp /etc/ssh/sshd_config{,.ori}
#<==這種方法的原理是bash對大括號的展開操作,/etc/ssh/sshd_config{,.ori}展開成/etc/
   ssh/sshd_config /etc/ssh/sshd_config.ori再傳給cp命令。

5.2.8 mv:移動或重命名文件

【命令星級】  ★★★★★

【功能說明】

mv命令可以理解爲英文單詞move的縮寫,其功能是移動或重命名文件(move/rename files)。

【語法格式】


mv  [option]  [source]  [dest] 
mv  [選項]    [源文件]  [目標文件]

說明:mv命令以及後面的選項和文件,每個元素之間都至少要有一個空格。

【選項說明】

表5-12針對mv命令的參數選項進行了說明。

表5-12 mv命令的參數選項及說明

【應用範例】

範例5-36:對文件改名的例子。


[[email protected] test]# ls
dir1  dir3  file1.txt  file3.txt  file5.txt
dir2  dir4  file2.txt  file4.txt  file6.txt
[[email protected] test]# mv file6.txt file7.txt #<==若file7.txt不存在,則將file6.txt
                                               重命名爲file7.txt。
[[email protected] test]# ls
dir1  dir3  file1.txt  file3.txt  file5.txt
dir2  dir4  file2.txt  file4.txt  file7.txt
[[email protected] test]# mv file5.txt file7.txt #<==若file7.txt存在,則將file5.txt覆蓋
                                                   file7.txt。
mv: overwrite `file7.txt'? y #<==由於系統默認爲mv設置了別名,因此會提示是否覆蓋。
[[email protected] test]# alias mv 
alias mv='mv -i' #<==-i參數的功能是若目標文件已經存在,則會詢問是否覆蓋。
[[email protected] test]# ls
dir1  dir2  dir3  dir4  file1.txt  file2.txt  file3.txt  file4.txt  file7.txt
[[email protected] test]# \mv file4.txt file7.txt #<==若是使用「\」屏蔽系統別名,就不會詢問
                                                是否覆蓋了。
[[email protected] test]# ls
dir1  dir2  dir3  dir4  file1.txt  file2.txt  file3.txt  file7.txt
[[email protected] test]# 

範例5-37:移動文件的例子。

移動單個文件的示例代碼如下:


[[email protected] test]# ls dir1/
sub1
[[email protected] test]# mv file7.txt dir1/ #<==dir1爲目錄且該目錄已存在,則移動file7.txt到
                                           dir1下,若dir1不存在,則重命名爲dir1的普通文件。
[[email protected] test]# ls dir1/
file7.txt  sub1 
移動多個文件:
[[email protected] test]# mv file1.txt file2.txt dir1/  #<==第一種方式:多個文件在前,目錄在後。
[[email protected] test]# ls dir1/
file1.txt  file2.txt  file7.txt  sub1 
[[email protected] test]# mv dir1/file* . #<==還原試驗環境,「file*」匹配所有以file開頭的文件

範例5-38:將源和目標調換移動文件到目錄(-t參數)。


[[email protected] test]# ls
dir1  dir2  dir3  dir4  file1.txt  file2.txt  file3.txt  file7.txt
[[email protected] test]# mv -t dir1/ file1.txt  file2.txt  file3.txt  file7.txt
    #<==使用-t參數將源和目標進行調換,-t後接目錄,最後是要移動的文件。
[[email protected] test]# ls dir1/
file1.txt  file2.txt  file3.txt  file7.txt  sub1

範例5-39:移動目錄的例子。


[[email protected] test]# ls
dir1  dir2  dir3  dir4
[[email protected] test]# mv dir1 dir5 #<==目錄dir5不存在,將目錄dir1改名爲dir5
[[email protected] test]# ls
dir2  dir3  dir4  dir5
[[email protected] test]# ls dir5/
file1.txt  file2.txt  file3.txt  file7.txt  sub1 
[[email protected] test]# mv dir2 dir5 #<==若存在目錄dir5,則將dir2移動到dir5中
[[email protected] test]# ls dir5/    
dir2  file1.txt  file2.txt  file3.txt  file7.txt  sub1
[[email protected] test]# mv dir3/ dir5/ #<==若在源目錄結尾加「/」則不影響結果,但爲了規範
                                       和簡單起見,建議不加「/」。
[[email protected] test]# ls
dir4  dir5
[[email protected] test]# ls dir5/
dir2  dir3  file1.txt  file2.txt  file3.txt  file7.txt  sub1

5.2.9 rm:刪除文件或目錄

【命令星級】  ★★★★★

【功能說明】

rm命令可以理解爲英文單詞remove的縮寫,其功能是刪除一個或多個文件或目錄(remove files or directories)。這是Linux系統裏最危險的命令之一,請慎重使用。

【語法格式】


rm  [option]  [file]
rm  [選項]    [<文件或目錄>] 

說明:rm命令以及後面的選項和文件目錄,每個元素之間都至少要有一個空格。

【選項說明】

表5-13針對rm命令的參數選項進行了說明。

表5-13 rm命令的參數選項及說明

【應用範例】

示例準備代碼如下:


[[email protected] ~]# mkdir -p /data/{dir1,dir2,dir3} #<==使用絕對路徑創建目錄。
[[email protected] ~]# touch /data/{file1.txt,file2.txt,file3.txt}
[[email protected] ~]# tree /data/                                
/data/
├── dir1
├── dir2
├── dir3
├── file1.txt
├── file2.txt
└── file3.txt
3 directories, 3 files
[[email protected] ~]# cd /data/
[[email protected] data]# ls
dir1  dir2  dir3  file1.txt  file2.txt  file3.txt

範例5-40:不帶參數刪除的實踐示例。


[[email protected] data]# rm file3.txt 
rm: remove regular empty file `file3.txt'? n
#<==若輸入y就會刪除文件,若不想刪除則輸入n。
[[email protected] data]# alias rm
alias rm='rm -i'  #<==上面會出現提示的原因是rm被設置了系統別名,默認使用了-i參數。
#<==屏蔽別名的方法已經在5.2.7節的cp命令講解中介紹過了,這裏不再贅述。

範例5-41:強制刪除的實踐示例。


[[email protected] data]# rm -f file3.txt #<==-f參數強制刪除,不提示。
[[email protected] data]# ls
dir1  dir2  dir3  file1.txt  file2.txt

提示:使用-f參數強制刪除會直接覆蓋系統定義的別名。

範例5-42:遞歸刪除的實踐示例。


[[email protected] data]# mkdir -p dir1/a/b
[[email protected] data]# tree dir1/
dir1/
└── a
    └── b
2 directories, 0 files 
[[email protected] data]# rm dir1    #<==若無參數就會無法刪除目錄。
rm: cannot remove `dir1': Is a directory
[[email protected] data]# rm -r dir1 #<==使用-r可以遞歸刪除,但會有確認提示,可以使用-f
                                   進行強制刪除。
rm: descend into directory `dir1'? y
rm: descend into directory `dir1/a'? y
rm: remove directory `dir1/a/b'? n
#<==備註:
加上-f參數就不需要一一確認了,例如rm -rf dir1。
若刪除的對象不是目錄(文件)就不要再使用-r參數了,這樣做會很危險,也沒有必要。

【有關刪除的實踐經驗分享】

常在河邊走,哪有不溼鞋!但如果能遵守下面的要領就可以少溼鞋甚至不溼鞋!

1)用mv替代rm,不要急着刪除,而是先移動到回收站「/tmp」。

2)刪除前請務必做好備份,最好是異機備份,出現問題隨時可還原。

3)如果非要刪除,則請用find替代rm,包括通過系統定時任務等清理文件方法。

下面是在生產環境中刪除文件或目錄的較安全的方法,命令如下:


find . -type f -name "*.txt" -mtime +7|xargs rm –f  #<==與xargs搭配使用,具體用
                                                        法見find命令的詳細講解。
find . -type f -mtime +7 -exec rm {} \;             #<==使用find的exec。

4)如果非要通過rm命令刪除,則請先切換目錄再刪,能不使用通配符的就儘量不用通配符。對文件的刪除禁止使用「rm-rf文件名」方法,因爲「rm-rf」誤刪目錄時並不會有提示,該操作非常危險。最多使用「rm-f文件名」方法,推薦使用「rm文件名」方法。


[[email protected] /]# cd /oldboy/
[[email protected] oldboy]# rm -f test1 test2

5)如果非要使用通配符,則請按下面的方法進行:


[[email protected] /]# cd /oldboy/
[[email protected] oldboy]# rm -f ./*  #<==加上「./」。
#<==禁止使用rm -fr /oldboy/*,這個命令如果多了空格可能會帶來災難。
[[email protected] /]# rm -fr /oldboy/*
#<==「*」的前面如果不小心多了空格,則會刪除當前目錄的所有內容,例如下面的命令。
[[email protected] /]# rm -fr /oldboy/ * #<==會把當前目錄(根)下面的目錄全部刪除。

6)額外再補充一點,要慎用「rsync--delete」。

多數情況下,刪除數據後是可以恢復的(例如,可通過恢復工具ext3grep來實現),但一定會影響業務,例如,造成停機,或者數據丟失了較長時間,用戶訪問不了等。未雨綢繆永遠比發生了再解決好得多。

更多內容可參考老男孩博客:http://oldboy.blog.51cto.com/2561410/1687300

5.3 Linux文件及目錄命令核心知識的試題及詳解

本節將要講解的試題是對讀者閱讀本章內容後的一個大考察,建議先不要看答案,看能否在Linux命令行下自行解答,然後再與參考答案進行對比,並深入瞭解題中遇到的相關Linux核心知識和操作規範。

5.3.1 有關cd/pwd/mkdir/ls命令試題

[考題]切換到「/tmp」目錄下,查看當前的工作位置,同時創建data1、data2、data3共3個目錄。

[參考答案]


[[email protected] ~]# cd /tmp        #<==切換到/tmp目錄。
[[email protected] tmp]# pwd          #<==查看當前的工作位置。
/tmp
[[email protected] tmp]# mkdir data1 data2 data3    #<==創建data1、data2、data3共3個目錄。
[[email protected] tmp]# ls           #<==操作後查看創建結果,這是個好的習慣。
data1  data2  data3  yum.log  yum_save_tx-2018-03-08-11-04z94H32.yumtx

[重點解析]

創建目錄可以一次性到位,且創建多級目錄一般要加-p參數,以防止出錯,示例代碼如下:


[[email protected] tmp]# cd ~          #<==切換到當前用戶家目錄下。
[[email protected] ~]# rm -fr /tmp/*   #<==刪除/tmp/所有內容,「*」代表所有,此命令很危險。
[[email protected] ~]# mkdir /tmp/data{1,2,3} -p    #<==利用大括號批量創建,加-p遞歸創建,
                                                  {1,2,3}等同於{1..3}。
[[email protected] ~]# ls /tmp         #<==接路徑直接查看指定目錄下的內容。
data1  data2  data3

5.3.2 有關touch/tree/file命令試題

[考題]接5.3.1節的考題,分別在data1、data2、data3目錄下創建3個文件,名字分別爲oldboy1、oldboy2、oldboy3,然後查看/tmp目錄的整個目錄結構情況,最後檢查下data1和oldboy1兩個對象的屬性。

[參考答案]

解答這道考題通常最容易想到的可能是分別在每個目錄下處理的笨辦法,其實還可以採用另一種快速的方法,注意,此考題依賴5.3.1節考題的結果,解題代碼如下:


[[email protected] ~]# touch /tmp/data{1..3}/oldboy{1..3}     #<==一步到位的答案。
[[email protected] ~]# tree /tmp   
-bash: tree: command not found  #<==tree命令沒有安裝的提示,前文tree命令中已經講解過了。
[[email protected] ~]# yum install tree -y  #<==安裝tree命令,需要系統能夠上網才行。
[[email protected] ~]# tree /tmp            #<==tree命令顯示目錄結構的結果。
/tmp
├── data1
│   ├── oldboy1
│   ├── oldboy2
│   └── oldboy3
├── data2
│   ├── oldboy1
│   ├── oldboy2
│   └── oldboy3
└── data3
    ├── oldboy1
    ├── oldboy2
    └── oldboy3

3 directories, 9 files
[[email protected] ~]# ls -l /tmp #<加-l參數,查看目錄下對象的屬性。
total 12
drwxr-xr-x. 2 root root 4096 Mar 10 17:11 data1 #<
「d」開頭表示data1是目錄。
drwxr-xr-x. 2 root root 4096 Mar 10 17:11 data2
drwxr-xr-x. 2 root root 4096 Mar 10 17:11 data3
[[email protected] ~]# ls -l /tmp/data1/
total 0
-rw-r–r--. 1 root root 0 Mar 10 17:11 oldboy1 #<==「-」開頭表示oldboy1是文件。
-rw-r–r--. 1 root root 0 Mar 10 17:11 oldboy2
-rw-r–r--. 1 root root 0 Mar 10 17:11 oldboy3


[重點解析]

·大括號{}的使用。

·ls-l命令的使用,以及通過屬性開頭的符號區分目錄和文件知識,「-」表示文件,「d」表示目錄。

5.3.3 有關cp命令的試題

[考題]將/etc/hosts文件複製到/tmp/data1下,然後將data1目錄複製到/opt下。

[參考答案]


[[email protected] ~]# cp /etc/hosts /tmp/data1/ #<==將/etc/hosts文件複製到/tmp/data1下。
[[email protected] tmp]# ls /tmp/data1
hosts  oldboy1  oldboy2  oldboy3           #<==複製結果。
[[email protected] ~]# cd /tmp
[[email protected] tmp]# cp -r data1 /opt/       #<==將data1目錄複製到/opt***意-r。
[[email protected] tmp]# tree /opt
/opt
├── data1    #<==複製結果。
│   ├── hosts
│   ├── oldboy1
│   ├── oldboy2
│   └── oldboy3
└── rh
2 directories, 4 files

[重點解析]

cp功能表示覆制文件或目錄,但默認不加參數則不能複製目錄。如果要複製目錄則必須使用-r或者-a參數,以下參數在前文講解命名時已經講解過,請讀者重點掌握。


-a  相當於-pdr,複製目錄也可以使用-a參數。
-r  遞歸,複製目錄,目錄及其子孫後代。
-p  複製文件同時保持文件屬性不變。

5.3.4 有關mv/rm命令的試題

[考題]將/tmp/data1目錄移動到/root目錄下,然後刪除/opt/data1目錄下的hosts文件,最後刪除/opt下的data1目錄。

[參考答案]


[[email protected] tmp]# cd /tmp    #<==mv是一個很危險的命令,操作前最好進入到對象的上一層次操作。
[[email protected] tmp]# mv data1 /root     #<==將/tmp/data1目錄移動到/root目錄下。
[[email protected] tmp]# cd /opt/data1      #<==rm是一個很危險的命令,操作前最好進入到對象的
                                          上一層操作。
[[email protected] data1]# rm hosts         #<==刪除前請確認。
rm: remove regular file `hosts'? yes  #<==輸入yes刪除。
[[email protected] data1]# ls
oldboy1  oldboy2  oldboy3             #<==hosts已刪。
[[email protected] data1]# rm -f oldboy1    #<==可以加-f直接強制刪除,不提示。
[[email protected] data1]# ls
oldboy2  oldboy3                      #<==oldboy1已刪。
[[email protected] data1]# cd ..            #<==切換到上一級目錄,這點在cd命令章節已講解過。
[[email protected] opt]# pwd                #<==確認當前所在的位置,防止誤刪。
/opt
[[email protected] opt]# ls                 #<==確認對象是否存在。
data1  rh
[[email protected] opt]# rm -fr data1       #<==強制刪除目錄和目錄下的所有文件,不提示(危險
                                          命令)。
[[email protected] opt]# ls
rh

[重點解析]

·操作rm、mv命令前,最好對操作的對象先做好備份。

·操作rm、mv命令最好切換到指定的目錄,且最好不要在根下直接操作。

·這裏的data1與/data1/是沒有區別的,都表示目錄及目錄下的所有內容,其他軟件場景可能會有區別。

·刪除目錄一般使用-rf參數,刪除前務必備份,以防誤刪。

·企業裏替代rm以及使用mv的注意事項請參見5.2.9節。

5.4 有關Linux命令的思維

學習Linux命令,僅僅停留在會操作的層面是遠遠不夠的,還要注意操作中可能會遇到的「坑」和解決手段,Linux運維是企業中最關鍵的崗位,錯按一個回車就可以讓數據丟失、服務器崩潰,因此,專業規範的操作是優秀的運維人員必須要掌握的基本技術。

5.5 本章相關問題

分別默寫出mkdir、ls、cp、rm命令的作用以及常用參數的功能,然後對照本書,檢查是否真的記住了。