第1章 Linux文件類基礎命令

1. 關於路徑和通配符

Linux中分絕對路徑和相對路徑,絕對路徑必定是從/開始寫的,相對路徑不從根開始寫,還可能使用路徑符號。 css

路徑展開符號:html

.  :(一個點)表示當前目錄
.. :(兩個點)表示上一層目錄
-  :(一個短橫線)表示上一次使用的目錄,例如從/tmp直接切換到/etc下,"-"就表示/tmp
~  :(波浪符號)表示用戶的家目錄,例如"~account"表示account用戶的家目錄
/dir/和/dir:通常都表示dir目錄和dir目錄中的文件。但在有些地方會嚴格區分是否加尾
              隨斜線,此時對於加了尾隨斜線的表示此目錄中的文件,不加尾隨斜線的表示
              該目錄自己和此目錄中的文件

切換路徑用cd命令; node

顯示當前所在目錄用pwd命令。若當前所在目錄爲連接目錄,使用pwd顯示的將是連接自身,使用-P選項將定位到連接的原始目錄。linux

[root@ansible6_node1 ~]# ll ; cd tmp; pwd; pwd -P
total 0
lrwxrwxrwx 1 root root 4 May 30 19:17 tmp -> /tmp
/root/tmp
/tmp

獲取文件名使用basename命令,獲取文件所在目錄使用dirname命令。注意,這兩個命令其實不太完善,它不會檢查文件或目錄是否存在,只要寫出來了就會去獲取。shell

[root@xuexi tmp]# basename /etc/shadow
shadow
[root@xuexi tmp]# basename /etc/
etc
[root@xuexi tmp]# dirname /etc/shadow
/etc
[root@xuexi tmp]# dirname /etc/    # 對目錄使用dirname獲取的是上級目錄
/
[root@server1 ~]# dirname /kalsldk/kdkskks/djfjdjdjsj   # 獲取不存在的目錄
/kalsldk/kdkskks

bash shell通配符:vim

可使用"*"、"?"、"[]"等的通配符來擴展路徑或文件名。例如, ls *.log 將列出當前路徑下全部以".log"字符結尾的文件名(但不包括"."開頭的隱藏文件)。windows

默認狀況下,bash提供的通配符規則比較弱,例如"*"沒法匹配文件名開頭的".",沒法匹配路徑分隔符號(即斜線"/"),但能夠經過set或shopt命令開啓額外的通配功能,實現更完善的通配符規則。緩存

例如,默認狀況下,想要匹配目錄/path下全部隱藏文件和非隱藏文件,以下:安全

ls  .*  *

開啓dotglob功能,"*"就能夠匹配以"."開頭的文件:bash

shopt -s dotglob
ls *

有時想要遞歸到目錄內部,又想要匹配文件名,例如想要遞歸找出多層目錄/path下全部的".css"文件,這時能夠開啓globstar功能,使用"兩星連珠"(**)就能夠匹配匹配路徑斜線。

shopt -s globstar       # 開啓星號匹配模式
ls /path/**/*.css       # 開啓後,使用兩個星號**就會匹配斜線

必需要說明的是,對於非bash內置命令,有些可能也提供了本身的通配符匹配方式,它們的通配模式和shell提供的可能並不同。例如find的"-name"選項就能夠採用本身的通配符,它的星號"*"能夠匹配以點開頭的隱藏文件,如 find /var/log -name "*.log" 。

2. 查看目錄內容(ls和tree)

ls命令列出目錄中的內容,和dir命令徹底等價。tree命令按樹狀結構遞歸列出目錄和子目錄中的內容,而ls使用-R選項時纔會遞歸列出。

注意:ls的結果中是以製表符分隔多個文件的。

2.1 ls命令

ls的各個選項說明以下:

-l:(long)長格式顯示,即顯示屬性等信息(包括mtime)。注意:顯示的目錄大小是節點所佔大小。像win同樣計算目錄大小時包括文件大小要用du -sh

-c:列出ctime

-u:列出atime

-d:(direcorty)查看目錄自己屬性信息,不查看目錄裏面的東西。不加-d會查看裏面文件的信息

-a:會顯示全部文件,包括兩個相對路徑的文件"."和".."以及以點開頭的隱藏文件

-A:會列出絕大多數文件,即忽略兩個相對路徑的文件"."和".."

-h:(human)人類可讀的格式,將字節換成k,將K換成M,將M換成G

-i:(inode)權限屬性的前面加上一堆數字

-p:對目錄加上/標識符以做區分

-F:對不一樣類型的文件加上不一樣標識符以做區分,對目錄加的文件也是/

-t:按修改時間排序內容。不加任何改變順序的選項時,ls默認按照字母順序排序

-r:反轉排序

-R:遞歸顯示

-S:按文件大小排序,默認降序排序

--color:顯示顏色

-m:使用逗號分隔各文件,固然,只適用於未使用長格式(ls -l)的狀況

-1:(數值一),以換行符分隔文件,固然,和-m或-l(小寫字母)是衝突的

-I pattern:忽略被pattern匹配到的文件

注意,ls以-h顯示文件大小時,通常顯示的都是不帶B的單位,如K/M/G,它們的轉換比例是1024,若是顯示的都是帶了B的,如KB/MB/GB,則它們的轉換比例爲1000而非1024,通常不多顯示帶B的大小。

不得不說,ls自己不能顯示出文件的全路徑名是一大缺陷,不過好在使用find命令能夠很簡單的就獲取到。

如下是使用ls -l顯示文件長格式的屬性。

[root@xuexi ~]# ll /tmp
drwxr-xr-x  2 root root 4096 Mar 26 16:44 test1

能夠查出7列屬性。

image

2.2 tree命令

有可能tree命令不存在,須要安裝tree包纔有(安裝:yum -y install tree)。

tree命令的選項說明以下:

【 匹配選項:】

-L:用於指定遞歸顯示的深度,指定的深度必須是大於0的整數。

-P:用於顯示通配符匹配模式的目錄和文件,可是無論是否匹配,目錄必定顯示。

-I:用於顯示除被通配符匹配外的全部目錄和文件。

【 顯示選項:】

-a:用於顯示隱藏文件,默認不顯示。

-d:指定只顯示目錄。

-f:指定顯示全路徑。

-i:不縮進顯示。和-f一塊兒使用頗有用。

-p:用於顯示權限位信息。

-h:用於顯示大小。

-u:顯示username或UID(當沒有username時只能顯示UID了)。

-g:顯示groupname或GID。

-D:顯示文件的最後一次Mtime。

--inodes:顯示inode號。

--device:顯示文件或目錄所屬的設備號。

-C:顯示顏色。

【 輸出選項:】

-o filename:指定將tree的結果輸出到filename文件中。

下圖是一個較全的輸出結果。

image

3. 文件的時間戳(atime/ctime/mtime)

文件的時間屬性有三種:atime/ctime/mtime。atime是access time,即上一次的訪問時間;mtime是modify time,是文件的修改時間;ctime是change time,也是文件的修改時間,只不過這個修改時間計算的inode修改時間,也就是元數據修改時間。文件還有一個建立時間(create time),大多數unix系統上都認爲這是個無用的屬性,通常工具沒法獲取這個時間,可是對於ext家族文件系統,經過它的底層調試工具debugfs能夠獲取create time。

但mtime只有修改文件內容纔會改變,更準確的說是修改了它的data block部分;而ctime是修改文件屬性時改變的,確切的說是修改了它的元數據部分,例如重命名文件,修改文件全部者,移動文件(移動文件沒有改變datablock,只是改變了其inode指針,或文件名)等.固然,修改文件內容也必定會改變ctime(修改文件內容至少已經修改了inode記錄上的mtime,這也是元數據),也就是說mtime的改變必定會引發ctime的改變。

對目錄而言,考慮目錄文件的data block,可知在目錄中建立、刪除文件以及目錄內其餘任意文件操做都會改變mtime,由於目錄裏的任何東西都是目錄中的內容;而目錄的ctime,除了目錄的mtime引發ctime改變以外,對目錄自己的元數據修改也會改變ctime。

總結下:

(1).atime只在文件被打開訪問時才改變,若不是打開文件編輯內容(如重定向內容到文件中),則ctime和mtime的改變不會引發atime的改變;

(2).mtime的改變必定引發ctime的改變,而訪問文件時(例如cat),atime不必定會改變,因此atime"改變"(這個改變是假象,見下文分析)不必定會影響ctime。(見下面的relatime說明)

3.1 關於relatime

atime/ctime/mtime是Posix標準要求操做系統維護的時間戳信息。可是每次將atime、ctime和mtime寫入到硬盤中(這些不會寫入緩存,只要修改就是寫入磁盤,即便從緩存讀取文件內容也如此)效率很低。有多低?下圖是寫ctime消耗的時間,幾乎總要花費零點幾秒。

mtime要被修改,必然是修改了文件內容,這時候將mtime寫入到硬盤中是應該的。可是atime和ctime呢?不少狀況下根本用不到atime和ctime,在頻繁訪問文件的時候,都要修改atime和ctime,這樣效率會下降不少不少,因此mount有個noatime選項來避免這種負面影響。

CentOS6引入了一個新的atime維護機制relatime:除非兩次修改atime的時間超過1天(默認設置86400秒),或者修改了mtime,不然訪問文件的inode不會引發atime的改變。換句話說,當cat一個文件的時候,它的atime可能會改變,可是你稍後再cat,它不會再改變。

因爲cat文件的時候atime可能不會改變,因此可能也就不會引發ctime的改變。

relatime維護的atime是能夠控制的,詳見man mount的relatime和redhat官方手冊

4. 文件/目錄的建立和刪除

4.1 建立目錄mkdir

mkdir [-mp] 目錄名

-m:表示建立目錄時直接設置權限

-p:表示遞歸建立多層目錄,即上層目錄不存在時也會直接將其建立出來(parent)

[root@xuexi ~]# mkdir /tmp/test1                 # 在tmp目錄中建立一個test1目錄
[root@xuexi ~]# mkdir -m 711 /tmp/test2          # 直接建立test2時就賦予權限711
[root@xuexi ~]# mkdir -p /tmp/test3/test4/test5  # 建立test5,此時會將不存在的test3和test4目錄也建立好

4.2 建立文件touch

touch file_name

[root@xuexi ~]# touch /tmp/test1/test1.txt 
[root@xuexi ~]# touch {1..10} # 建立文件名爲1-10的文件

多個{}還能夠交換擴展。相似(a+b)(c+d)=ac+ad+bc+bd。

[root@xuexi ~]# touch {a,b}_{c,d} # 建立a_c、a_d、b_c、b_d四個文件

touch主要是修改文件的時間戳信息,當touch的文件不存在時就自動建立該文件。可使用 touch –c 來取消建立動做。

touch能夠更改最近一次訪問時間(atime),最近一次修改時間(mtime),文件屬性修改時間(ctime),這些時間能夠經過命令stat file來查看。其中ctime是文件屬性上的更改,即元數據的更改,好比修改權限。

touch -a修改atime,-m修改mtime,沒有修改ctime的選項。由於使用touch改變atime或mtime,同時也都會改變ctime,雖然說atime並不老是會影響ctime(如cat文件時)。

-t選項表示使用"[[CC]YY]MMDDhhmm[.ss]"格式的時間替代當前時間。

shell> touch -a -t 201212211212 file # 將file文件的atime修改成2012年12月21號12點12分

-d選項表示使用指定的字符串描述時間格式來替代當前時間,如"3 days ago","next Sunday"等不少種格式。

因此,touch命令選項說明以下:

-c:強制不建立文件

-a:修改文件access time(atime)

-m:修改文件modification time(mtime)

-t:使用"[[CC]YY]MMDDhhmm[.ss]"格式的時間替代當前時間

-d:使用字符串描述的時間格式替代當前時間

4.3 刪除文件/目錄

rm [-rfi] file_name

-r:表示遞歸刪除,刪除目錄時須要加此參數

-i:詢問是否刪除(yes/no)

-f:強制刪除,不進行詢問

[root@xuexi ~]# rm -rf /tmp/test2

刪除空目錄時還可使用rmdir。

在刪除文件以前,必定必定要肯定是否真的刪除。最好使用rm -i(默認已經在~/.bashrc中定義了該別名),除非在腳本中,不然不要輕易使用-f選項。已經有很是多的人不當心rm -rf *和rm -rf /NNNNN了。例如想刪除"rm –rf /abc*",結果習慣性的多敲了一個空格"rm –rf /abc *",完了。

5. 查看文件類型file命令

這是一個簡單查看文件類型的命令,查看文件是屬於二進制文件仍是數據文件仍是ASCII文件。

[root@xuexi tmp]# file /etc/aliases.db
/etc/aliases.db: Berkeley DB (Hash, version 9, native byte-order)  # 數據文件
[root@xuexi tmp]#
file ~/.bashrc /root/.bashrc: ASCII text # ASCII文件
[root@xuexi tmp]#
file /bin/ls /bin/ls: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, stripped

除了基本的查看文件類型的功能外,file還有一個"-s"選項,是一個超強力的選項,能夠查看設備的文件系統類型。像有些分區工具如parted在分區時是能夠指定文件系統的(雖然不建議這麼作,CentOS 7的parted版本中已經取消了該功能),但在分區後格式化前,通常是比較難查看該分區的文件系統類型的,但使用file能夠查看到。

[root@server1 ~]# file -s /dev/sda1
/dev/sda1: Linux rev 1.0 ext4 filesystem data (needs journal recovery) (extents) (huge files)
[root@server1
~]# file -s /dev/sda /dev/sda: x86 boot sector; GRand Unified Bootloader, stage1 version 0x3, boot drive 0x80, 1st sector stage2 0x7f86, GRUB version 0.94; partition 1: ID=0x83,
active, starthead 32, startsector 2048, 512000 sectors; partition 2: ID=0x83, starthead 254, startsector 514048, 37332992 sectors; partition 3: ID=0x82,
starthead 254, startsector 37847040, 4096000 sectors, code offset 0x48

6. 文件/目錄複製和移動

6.1 cp命令

cp [-apdriulfs] src dest # 複製單文件或單目錄

cp [-apdriuslf] src1 src2 src3......dest_dir # 複製多文件、目錄到一個目錄下

選項說明:

-p: 文件的屬性(權限、屬組、時間戳)也複製過去。若是不指定p選項,誰執行復制動做,文件全部者和組就是誰。

-r或-R:遞歸複製,經常使用於複製非空目錄。

-d:複製的源文件若是是連接文件,則複製連接文件而不是指向的文件自己。即保持連接屬性,複製快捷方式自己。若是不指定-d,則複製的是連接所指向的文件。

-a:a=pdr三個選項。歸檔拷貝,經常使用於備份。

-i:複製時若是目標文件已經存在,詢問是否替換。

-u:(update)若目標文件和源文件同名,但屬性不同(如修改時間,大小等),則覆蓋目標文件。

-f:強制複製,若是目標存在,不會進行-i選項的詢問和-u選項的考慮,直接覆蓋。

-l:在目標位置創建硬連接,而不是複製文件自己。

-s:在目標位置創建軟連接,而不是複製文件自己(軟連接或符號連接至關於windows的快捷方式)。

通常使用cp -a便可,對於目錄加上-r選項便可。

注意,bash內置命令在進行通配符匹配文件的時候,"*"、"?"、"[]"是沒法匹配到以"."開頭的文件的,因此"*"不會匹配隱藏文件。要通配隱藏文件,使用"."代替上述幾種通配元字符便可,它能匹配除了"."和".."這兩個特殊目錄外的全部文件。它並不是通配符,而是表示當前目錄,顯然直接複製目錄,是能夠將隱藏文件複製走的。

例如,複製/etc/skel目錄下全部文件包括隱藏文件到/tmp目錄下。

cp -a /etc/skel/. /tmp

若是有重複文件,則即便加上-f選項,也同樣會交互式詢問。解決方法能夠是使用"yes"這個工具,它會不斷的生成y字母直到進程被殺掉,固然也能夠自行指定要生成的字符串。

yes | cp -a /etc/skel/. /tmp

6.2 scp命令和執行過程分析

scp是基於ssh的安全拷貝命令(security copy),它是從古老的遠程複製命令rcp改變而來,實現的是在host與host之間的拷貝,能夠是本地到遠程的、本地到本地的,甚至能夠遠程到遠程複製。注意,scp可能會詢問密碼。

若是scp拷貝的源文件在目標位置上已經存在時(文件同名),scp會替換已存在目標文件中的內容,但保持其inode號。

若是scp拷貝的源文件在目標位置上不存在,則會在目標位置上建立一個空文件,而後將源文件中的內容填充進去。

之因此解釋上面的兩句,是爲了理解scp的機制,scp拷貝本質是隻是填充內容的過程,它不會去修改目標文件的不少屬性,對於從遠程複製到另外一遠程時,其機制見後文。

scp [-12BCpqrv] [-l limit] [-o ssh_option] [-P port] [[user@]host1:]file1 ... [[user@]host2:]file2

選項說明:

-1:使用ssh v1版本,這是默認使用協議版本

-2:使用ssh v2版本

-C:拷貝時先壓縮,節省帶寬

-l limit:限制拷貝速度,Kbit/s.

-o ssh_option:指定ssh鏈接時的特殊選項,通常用不上。偶爾在鏈接過程當中等待提示輸入密碼較慢時,能夠設置GSSAPIAuthentication爲no

-P port:指定目標主機上ssh端口,大寫的字母P,默認是22端口

-p:拷貝時保持源文件的mtime,atime,owner,group,privileges

-r:遞歸拷貝,用於拷貝目錄。注意,scp拷貝遇到連接文件時,會拷貝連接的源文件內容填充到目標文件中(scp的本質就是填充而非拷貝)

-v:輸出詳細信息,能夠用來調試或查看scp的詳細過程,分析scp的機制

示例:

1.把本地文件/home/a.tar.tz拷貝到遠程服務器192.168.0.2上的/home/tmp,鏈接時使用遠程的root用戶:

scp /home/a.tar.tz root@192.168.0.2:/home/tmp/

2.目標主機不寫路徑時,表示拷貝到對方的家目錄下:

scp /home/a.tar.tz root@192.168.0.2

3.把遠程文件/home/a.tar.gz拷貝到本機:

scp root@192.168.0.2:/home/a.tar.tz # 不接本地目錄表示拷貝到當前目錄

scp root@192.168.0.2:/home/a.tar.tz /tmp # 拷貝到本地/tmp目錄下

4.拷貝遠程機器的/home/目錄到本地/tmp目錄下。

scp -r root@192.168.0.2:/home/ /tmp

5.從遠程主機192.168.100.60拷貝文件到另外一臺遠程主機192.168.100.62上。

scp root@192.168.100.60:/tmp/copy.txt root@192.168.100.62:/tmp

在遠程複製到遠程的過程當中,例如在本地執行scp命令將A主機(192.168.100.60)上的/tmp/copy.txt複製到B主機(192.168.100.62)上的/tmp目錄下,若是使用-v選項查看調試信息的話,會發現它的步驟相似是這樣的。

# 如下是從結果中提取的過程

# 首先輸出本地要執行的命令

Executing: /usr/bin/ssh -v -x -oClearAllForwardings yes -t -l root 192.168.100.60 scp -v /tmp/copy.txt root@192.168.100.62:/tmp

 

# 從本地鏈接到A主機

debug1: Connecting to 192.168.100.60 [192.168.100.60] port 22.

debug1: Connection established. 

 

# 要求驗證本地和A主機之間的鏈接

debug1: Next authentication method: password

root@192.168.100.60's password:

 

# 將scp命令行修改後發送到A主機上

debug1: Sending command: scp -v /tmp/copy.txt root@192.168.100.62:/tmp

 

# 在A主機上執行scp命令

Executing: program /usr/bin/ssh host 192.168.100.62, user root, command scp -v -t /tmp

 

# 驗證A主機和B主機之間的鏈接

debug1: Next authentication method: password

root@192.168.100.62's password:

 

# 從A主機上拷貝源文件到最終的B主機上

debug1: Sending command: scp -v -t /tmp

Sending file modes: C0770 24 copy.txt

Sink: C0770 24 copy.txt

copy.txt 100% 24 0.0KB/s 

 

# 關閉本地主機和A主機的鏈接

Connection to 192.168.100.60 closed.

也就是說,遠程主機A到遠程主機B的複製,其實是將scp命令行從本地傳遞到主機A上,由A本身去執行scp命令。也就是說,本地主機不會和主機B有任何交互行爲,本地主機就像是一個代理執行者同樣,只是幫助傳送scp命令行以及幫助顯示信息。

其實從本地主機和主機A上的~/.ssh/know_hosts文件中能夠看出,本地主機只是添加了主機A的信息,並無添加主機B的信息,而在主機A上則添加了主機B的信息。

image

6.3 mv命令

mv命令移動文件和目錄,還能夠用於重命名文件或目錄。

mv [-iuf] src dest # 移動單個文件或目錄

mv [-iuf] src1 src2 src3 dest_dir # 移動多個文件或目錄

選項說明:

--backup[=CONTROL]:若是目標文件已存在,則對該文件作一個備份,默認備份文件是在文件名後加上波浪線,如/b.txt~

-b:相似於--backup,但不接受參數, 默認備份文件是在文件名後加上波浪線,如/b.txt~

-f:若是目標文件已存在,則強制覆蓋文件

-i:若是目標文件已存在,則提示是否要覆蓋,這是alias mv的默認選項

-n:若是目標文件已存在,則不覆蓋已存在的文件

     若是同時指定了-f/-i/-n,則後指定的生效

-u:(update)若是源文件和目標文件不一樣,則移動,不然不移動

mv默認已是遞歸移動,不須要-r參數。

6.4 mv的一個經典問題(mv的本質)

該問題涉及文件系統操做文件的機制,若不理解,請先深刻學習文件系統

mv不能實現裏層同名目錄覆蓋外層同名目錄。如/tmp下有a目錄,a目錄裏還有a目錄,將不能實現/tmp/a/a移動到/tmp。

[root@toystory tmp]# tree -L 3 a -fC

a
└── a/a
├── a/a/a
2 directories, 1 file

[root@toystory tmp]# mv a/* .
mv: overwrite `./a'? y
mv: cannot move `a/a' to `./a': Directory not empty
 
[root@toystory tmp]# mv -f /tmp/a/* /tmp mv: cannot move `/tmp/a/a' to `/tmp/a': Directory not empty

要解釋爲什麼會如此,先說明移動和覆蓋動做的本質。

同文件系統下移動文件其實是修改目標文件所在目錄的data block,向其中添加一行指向inode table中待移動文件的inode的指針,若是目標路徑下有同名文件,則會提示是否覆蓋,其實是覆蓋指向該同名文件的inode指針,因爲同名文件的inode記錄指針被覆蓋,就沒法再找到該文件的data block,因此該文件被標記爲刪除。

跨文件系統移動文件的本質:若是目標路徑下沒有同名文件,則先爲此文件分配一個inode號,並在目標目錄的data block中添加一條指向該inode號的新記錄(是全新的),而後將文件複製到目標位置,複製成功則刪除源文件,複製失敗則保留源文件;若是目標路徑下有同名文件,則提示是否要覆蓋,若是選擇覆蓋,則將該同名文件的inode指針指向新分配的inode號,而後將文件複製到目標位置,複製成功則刪除源文件,複製失敗則保留源文件。

也就是說,同文件系統下移動文件時,inode記錄不變(如inode號),固然,時間戳是必定會改變的,由於移動過程當中修改了inode指向data block的指針。而跨文件系統下移動文件時,inode記錄徹底改變,它是新添加的記錄。

再考慮上面的問題,同文件系統下移動文件時先在目標位置/tmp的data block中添加一條記錄,若是同名則提示覆蓋,覆蓋時會先刪除/tmp的data block中的a對應的記錄,再添加將要移動文件的記錄。從上面的結果也能夠看出是先提示覆蓋再提示目錄非空的錯誤。

設想下,若是/tmp/a/a移動到/tmp下並重命名爲b,則其動做是直接向/tmp的data block中添加b的記錄,若是此時正好/tmp下已有b目錄,則先刪除/tmp的data block中b目錄對應的記錄,再添加移動後的b記錄。

可是如今不是重命名爲b,而是覆蓋/tmp/a,此時的動做按原理應該是先提示是否覆蓋,若是是,則刪除/tmp的data block中a對應的記錄,但因爲此時/tmp/a目錄中還有文件,該記錄沒法刪除(由於若是要刪除了該記錄,表明刪除了/tmp/a整個目錄,而刪除整個/tmp/a目錄須要刪除裏面全部的文件,在刪除它們以前的一個動做是把/tmp/a中的全部目錄和文件的inode號標記爲未使用,但此刻要移動的源目錄/tmp/a/a是在使用當中的),因此提示目錄非空而沒法刪除,這裏所指的非空目錄指的是/tmp/a,而非是/tmp/a/a非空。

可是在Windows操做系統下,裏層目錄是能夠直接覆蓋外層同名目錄的,這和文件系統的行爲有關。

其實在這個問題中,能夠看出mv的不少原理。

7. 查看文件內容

7.1 cat命令

輸出一個或多個文件的內容。

cat [OPTION]... [FILE]...

選項說明

-n:顯示全部行的行號

-b:顯示非空行的行號

-E:在每行行尾加上$符號

-T:將TAB符號輸出爲"^I"

-s:壓縮連續空行爲單個空行

cat還有一個重要功能,容許將分行鍵入的內容輸入到一個文件中去。

首先測試<<eof,這表示將鍵入的內容追加到標準輸入stdin中(不是從標準輸入中讀取), eof能夠隨便使用其餘符號代替。

[root@xuexi tmp]# cat <<eof
> abc.com
> eof
abc.com

再測試<eof,發現沒有輸入的機會,而且此時只能使用eof做爲符號,EOF或其餘任何都不能夠。由於<eof是讀取標準輸入,會將eof當成輸入文件處理。因此必定要使用<<eof,這表示here document,而兩個eof正是document的起始和結束標誌。

[root@xuexi tmp]# cat <eof
[root@xuexi tmp]# cat <eox
-bash: eox: No such file or directory

[root@xuexi tmp]# cat <EOF
-bash: EOF: No such file or directory

再進一步測試<<eof的功能,將鍵入的內容重定向到文件而非標準輸入中。這時有兩種書寫方案:

第一種方案:>>filename<<eof或>filename<<eof

[root@xuexi ~]# cat >>/tmp/test.txt<<EOF # 輸入到這裏按回車鍵繼續輸入下一行
> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # 按回車輸入下一行
> yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy # 按回車輸入下一行
> zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz # 按回車輸入下一行
> EOF # 頂格寫EOF結束輸入

第二種方案:<<eof>filename或<<eof>>filename

[root@xuexi tmp]# cat <<eof>log.txt
> abc.com
> eof

兩種方案結果是同樣的,且老是使用<<eof,只不過所寫的位置不一樣而已,無論寫在哪一個位置,它都表示將鍵入的內容追加到標準輸入。而後再使用>filename或>>filename控制重定向的方式,將標準輸入中的內容重定向到filename文件中。

7.2 tac

tac和cat字母正好是相反的,其做用也是和cat相反的,它會反向輸出行,將最後一行放在第一行的位置輸出,依此類推。可是,tac沒有顯示行號的參數。

shell> echo -e '1\n2\n3\n4\n5' | tac
5
4
3
2
1

7.3 head

head打印前面的幾行。

head [-n num] | [-num] [-v] filename

-n:顯示前num行;若是num是負數,則顯示除了最後|num|(絕對值)行的其他全部行,即顯示前"總行數 - |num|"

-v:會顯示出文件名

-n num是顯示文件的前num行,num能夠是+/-或不加正負號的整數,若是是正整數或不寫+號,則顯示前num行。若是是負整數,則從後向前數num行,並打印除了這些行的前面全部的行,即打印除了最後num行的全部行,也即總行數減num的前正數行。不寫-n時默認是前10行。正整數時"-n num"能夠直接簡寫"-num"。

無論怎麼樣,它取的都是前幾行,哪怕是負整數也是前幾行。

示例:

[root@xuexi ~]# echo -e '1\n2\n3\n4\n5' | head     # 取出默認前10行,但總共纔有5行。
1
2
3
4
5

[root@xuexi ~]# echo -e '1\n2\n3\n4\n5' | head -2     # 取出前2行
1
2

或者

[root@xuexi ~]# echo -e '1\n2\n3\n4\n5' | head -n 2 # 取出前2行
1
2

[root@xuexi ~]# echo -e '1\n2\n3\n4\n5' | head -n -1 # 取出前5-1=4行
1
2
3
4

7.4 tail

tail和head相反,是顯示後面的行,默認是後10行。

tail [OPTION]... [FILE]...

選項說明:

-n:輸出最後num行,若是使用-n +num則表示輸出從第num行開始的全部行

-f:監控文件變化

--pid=PID:和-f一塊兒使用,在給定PID的進程死亡後,終止文件監控

-v:顯示文件名

"-n -num"或"-num"或"-n num"(num爲正整數)表示輸出最後的num行。使用"-n +num"(num爲正整數)則表示輸出從第num行開始的全部行。

[root@xuexi ~]# echo -e '1\n2\n3\n4\n5' | tail -3         # 等價於 tail -n 3和tail -n -3
3
4
5

[root@xuexi tmp]# seq 6 | tail -n +3       # 打印除了前3-1=2行的全部行
3
4
5
6

tail還有一個重要的參數-f,監控文件的內容變化。當一個用戶不斷修改某個文件的尾部,另外一個用戶就能夠經過這個命令來刷新並顯示這些修改後的內容。

7.5 nl

以行號的方式查看內容。

經常使用"-b a",表示不管是否空行都顯示行號,等價於cat -n;不寫選項時,默認"-b t",表示空行不顯示行號,等價於cat -b。

[root@xuexi ~]# nl /etc/issue # 默認空行不顯示行號
1 CentOS release 6.6 (Final)
2 Kernel \r on an \m

[root@xuexi ~]# nl -b a /etc/issue
1 CentOS release 6.6 (Final)
2 Kernel \r on an \m
3

7.6 more和less

按頁顯示文件內容。使用more時,使用/搜索字符串,按下n或N鍵表示向下或向上繼續搜索。使用less時,還多了一個搜索功能,使用?搜索字符串,一樣,使用n或N鍵能夠向上或向下繼續搜索。

7.7 比較文件內容

shell> diff file1 file2

shell> vimdiff file1 file2

8. 文件查找類命令

搜索文件的路徑在何處以及文件的名稱爲什麼。

8.1 which

顯示命令或腳本的全路徑,默認也會將命令的別名顯示出來。

shell> which mv

alias mv='mv -i'
       /bin/mv

8.2 whereis

找出二進制文件、源文件和man文檔文件。

shell> whereis cd

cd: /usr/bin/cd /usr/share/man/man1/cd.1.gz /usr/share/man/man1p/cd.1p.gz /usr/share/man/mann/cd.n.gz

8.3 whatis

列出給定命令(並不是必定是命令)的man文檔信息。

shell> whatis passwd

sslpasswd (1ssl) - compute password hashes
passwd (1) - update user's authentication tokens
passwd (5) - password file

根據上面的結果,執行:

man 1 passwd # 獲取passwd命令的man文檔

man 5 passwd # 獲取password文件的man文檔,文件類的man文檔說明的是該文件中各配置項意義

man sslpasswd # 獲取sslpasswd命令的man文檔,其實是openssl passwd的man文檔

8.4 locate

沒什麼好說的。

8.5 find

內容太多,使用兩篇單獨的文章解釋

Linux find經常使用用法示例

Linux find運行機制詳解

相關文章
相關標籤/搜索