struct stat { dev_t st_dev; /* 設備*/ ino_t st_ino; /* 節點*/ mode_t st_mode; /* 模式*/ nlink_t st_nlink; /* 硬連線*/ uid_t st_uid; /* 用戶ID */ gid_t st_gg;組ID */ dev_t st_rdev; /*裝置類型*/ off_t st_off; /* 檔案位元組數*/ unsigned long st_blksize; /* 區塊大小*/ unsigned long st_blocks; /* 區塊數*/ time_t st_atime; /* 最後一次存取時間*/ time_t st_mtime; * 最後一次修改時間*/ time_t st_ctime; /* 最後一次改變時間(指屬性) */};下面逐次來了解這些屬性,如果需要查看某個文件屬性,用
stat命令就可,它會依照上面的結構體把資訊列出來。另外,
ls指令跟上一定參數後也可以顯示檔案的相關屬性,例如
-l參數。
文件類型對應上面的
st_mode, 文件類型有很多,例如常規文件、符號連結(硬連結、軟連結)、管道文件、設備文件(符號設備、塊設備)、socket文件等,不同的文件類型對應不同的功能和作用。
$ ls -ltotal 12drwxr-xr-x 2 root root 4096 2007-12-07 20:08 directory_fileprw-r--r-- 1 root root 0 2007-12-07 20:18 fifo_pipe brw-r-1 root root 3, 1 2007-12-07 21:44 hda1_block_dev_filecrw-r--r-- 1 root root 1, 3 2007-12-07 21:43 null_char_dev_file-rw-r--r-- 2 root root 506 20071 :55 regular_file-rw-r--r-- 2 root root 506 2007-12-07 21:55 regular_file_hard_linklrwxrwxrwx 1 root root 12 2007-12-07 20:15 regular_file_soft_link -> regular_107 20:15 regular_file_soft_link -> regular_$ statize 403:000:004 ? Blocks: 8 IO Block: 4096 directoryDevice: 301h/769d Inode: 521521 Links: 2Access: (0755/drwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)Access: 20077 :08:18.000000000 +0800Modify: 2007-12-07 20:08:18.000000000 +0800Change: 2007-12-07 20:08:18.000000000 +0800$ 00:000$ 00:0000000 +0800$ charstat: `nize_dev. IO Block: 4096 character special fileDevice: 301h/769d Inode: 521240 Links: 1 Device type: 1,3Access: (0644/crw-r--r--) Uid: ( 0/ ) Gidroot: ( 0/ /crw-r--r--) Uid: ( 0/ ) Gidroot: (root/ ) Access: 2007-12-07 21:43:38.000000000 +0800Modify: 2007-12-07 21:43:38.000000000 +0800Change: 2007-12-07 21:43:38.000008000
說明:透過
ls命令結果每行的第一個字元可以看到,它們之間都不相同,這正好反應了不同檔案的類型。
d表示目錄,
-表示普通文件(或硬連結),
l表示符號鏈接,
p表示管道文件,
b和
c分別表示塊設備和字元設備(另外
s表示
socket文件)。在
stat在命令的結果中,可以在第二行的最後找到說明,從上面的操作可以看出,
directory_file是目錄,
stat命令的結果中用
directory表示,而
null_char_dev_file它則用
character special file說明。
通常只會用到目錄、普通文件、以及符號鏈接,很少碰到其他類型的文件,不過這些文件還是各有用處的,如果要做嵌入式開發或者進程通信等,可能會涉及到設備文件、有名管道(FIFO)。以下透過簡單的操作來反應它們之間的差異(具體原理會在下一節《Shell 程式設計範例之檔案系統》介紹,如果有興趣,也可以提前到網路上找找設備檔案的作用、區塊設備和字元設備的區別、以及驅動程式中如何編寫相關設備驅動等)。
對於普通文件:就是一系列字元的集合,所以可以讀、寫等
$ echo hello, world > regular_file$ cat regular_filehello, world
在目錄中可以建立新文件,所以目錄還有叫法:文件夾,到後面會分析目錄文件的結構體,它實際上存放了它下面的各個文件的文件名。
$ cd directory_file$ touch file1 file2 file3
對於有名管道,操作起來比較有趣:如果要讀它,除非有內容,否則阻塞;如果要寫它,除非有人來讀,否則阻塞。它常用於進程通訊中。可以打開兩個終端
terminal1和
terminal2,試試看:
terminal1$ cat fifo_pipe #剛開始阻塞在這裡,直到下面的寫入動作發生,才列印test字串terminal2$ echo test > fifo_pipe
關於區塊設備,字元設備,設備檔案對應
/dev/hda1和
/dev/null,如果用過U 盤,或是寫過簡單的腳本的話,這樣的用法應該用過::-)
$ mount hda1_block_dev_file /mnt #掛載硬碟的第一個分區到/mnt下(關於掛載的原理,在下一節討論)$ echo fewfewfef > /dev/null #/dev/null像個黑洞,什麼東西丟進去都消失殆盡
最後兩個文件分別是
regular_file文件的硬鏈接和軟鏈接,去讀寫它們,他們的內容是相同的,不過去刪除它們,他們卻互不相干,硬鏈接和軟鏈接又有何不同呢?前者可以說就是原文件,後者呢只是有那麼一個
inode,但沒有實際的儲存空間,建議用
stat命令查看它們之間的區別,包括它們的
Blocks,
inode等值,也可以考慮用
diff比較它們的大小。
$ ls regular_file*ls regular_file* -l-rw-r--r-- 2 root root 204800 2007-12-07 22:30 regular_file-rw-r--r-- 2 root root 204800 2007-12-007 222-007 :30 regular_file_hard_linklrwxrwxrwx 1 root root 12 2007-12-07 20:15 regular_file_soft_link -> regular_file$ rm regular_file # 刪除原始檔案$ cat regular_file_hard_link # 硬連結還在,而且裡面的內容還有呢fefe$ cat reg_ _soft_link_plink: _soft:_o_oft:$ cat reglink:_soft_file_oo:_soft catage_link:$ cat 零: directory
雖然軟連結檔案本身還在,不過因為它本身不儲存內容,所以讀不到東西,這就是軟連結和硬連結的區別。
要注意的是,硬連結不可以跨檔案系統,而軟連結則可以。另外,也不允許為目錄建立硬連結。
文件類型從Linux 檔案系統那麼一個層級分了以上那麼多類型,不過普通文件還是可以再分的(根據文件內容的」資料結構「分),例如常見的文字文件,可執行的
ELF文件,
odt文件,
jpg圖片格式,
swap分區文件,
ELF文件的工作原理,如果有興趣,建議閱讀參考資料中和
ELF文件相關部分,這一部分對於嵌入式Linux 工程師至關重要。
雖然各類普通文件都有專屬的操作工具,但是還是可以直接讀取、寫它們,這裡先提到這麼幾個工具,回頭討論細節。
od:以八進位或其他格式「匯出」文件內容。
strings:讀出文件中的字元(可列印的字元)
gcc,
gdb,
readelf,objdump
等:ELF
文件分析、處理工具(gcc
編譯器、gdb
偵錯工具,readelf
分析ELF 文件,objdump` 反編譯工具)
再補充一個非常重要的指令,
file,這個指令用來查看各類文件的屬性。和
stat命令相比,它可以進一步識別普通文件,即
stat命令顯示的
regular file。因為
regular file可以有各種不同的結構,因此在作業系統的支援下得到不同的解釋,執行不同的動作。雖然,Linux 下,文件也會加上特定的後綴以便用戶能夠方便地識別文件的類型,但是Linux 作業系統根據文件頭識別各類文件,而不是文件後綴,這樣在解釋相應的文件時就更不容易出錯。以下簡單介紹
file命令的用法。
$ file ././: directory$ file /etc/profile/etc/profile: ASCII English text$ file /lib/libc-2.5.so/lib/libc-2.5.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), 不 stripped$ file /bin/test/bin/test: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), stripped$ file /dev/hda/dev/hda: block special (3/ 0)$ file /dev/console/dev/console: character special (5/1)$ cp /etc/profile .$ tar zcf profile.tar.gz profile$ file profile.tar.gzprofile.tar.gz: gzip compressed data, from Unix, last modified: Tue Jan 4 18:53: 53 2000$ mkfifo fifo_test$ file fifo_testfifo_test: fifo (named pipe)
更多用法見
file命令的手冊,關於
file命令的實作原理,請參考
magic的手冊(看看
/etc/file/magic文件,了解什麼是文件的
magic number等)。
Linux 作為一個多用戶系統,為多用戶使用同一個系統提供了極大的方便,例如對於系統上的文件,它透過屬主來區分不同的用戶,以便分配它們對不同文件的操作權限。為了更方便地管理,文件屬主包括該文件所屬用戶,以及該文件所屬的用戶群組,因為用戶可以屬於多個群組。先來簡單介紹Linux 下使用者和群組的管理。
Linux 下提供了一組命令用於管理使用者和群組,例如用於建立使用者的
useradd和
groupadd,用於刪除用戶的
userdel和
groupdel,另外,
passwd命令用於修改用戶密碼。當然,Linux 也提供了兩個相應的配置,即
/etc/passwd和
/etc/group,另外,有些系統還把密碼單獨放到了設定文件
/etc/shadow中。關於它們的詳細用法請參考後面的資料,這裡不再介紹,僅介紹文件和使用者之間的一些關係。
$ chown 使用者名稱:群組名稱檔案名
如果要遞歸地修改某個目錄下所有檔案的屬主,可以添加
-R選項。
從本節開頭列出的文件結構體中,可以看到只有用戶
ID和組
ID的訊息,但
ls -l的結果卻顯示了使用者名稱和群組名稱訊息,這個是怎麼實現的呢?下面先看看
-n的結果:
$ ls -n regular_file-rw-r--r-- 1 0 0 115 2007-12-07 23:45 regular_file$ ls -l regular_file-rw-r--r-- 1 root root 115 2007-12-07 23:45 regular_file
可以看到,
ls -n顯示了用戶
ID和組
ID,而
ls -l顯示了它們的名字。還記得上面提到的兩個設定文件
/etc/passwd和
/etc/group文件麼?它們分別存放了用戶
ID和用戶名,群組
ID和組名的對應關係,因此很容易想到
ls -l命令在實現時是如何通過文件結構體的
ID資訊找到它們對應的名字資訊的。如果想對
ls -l命令的實現有更進一步的了解,可以用
strace追蹤看看它是否讀取了這兩個設定檔。
$ strace -f -o strace.log ls -l regular_file$ cat strace.log | egrep passwd|group|shadow2989 open(/etc/passwd, O_RDONLY) = 32989 open(/etc/group, O_RDONLY) = 3
說明:
strace可以用來追蹤系統呼叫和訊號。如同
gdb等其他強大的工具一樣,它是基於系統的
ptrace系統呼叫實作。
實際上,把屬主和權限分開介紹不太好,因為只有它們兩者結合才使得多用戶系統成為可能,否則無法隔離不同用戶對某個文件的操作,所以下面來介紹文件操作權限。
從
ls -l命令的結果的第一列的後9 個字元中,可以看到類似這樣的訊息
rwxr-xr-x,它們對應於文件結構體的
st_mode部分(
st_mode包含文件類型資訊和文件權限資訊兩部分)。這類資訊可以分成三個部分,即
rwx,
rx,
rx,分別對應該文件所屬使用者、所屬群組、其他群組對該文件的操作權限,如果有
rwx中任何一個表示可讀、可寫入、可執行,如果為
-表示沒有這個權限。對應地,可以用八進制來表示它,例如
rwxr-xr-x就可表示成二進位111101101,對應的八進位則為755 。正因為如此,要修改文件的操作權限,也可以有多種方式來實現,它們都可透過
chmod命令來修改。
比如,把
regular_file的檔案權限修改為所有使用者都可讀、可寫入、可執行,即
rwxrwxrwx,也可表示為111111111,翻譯成八進制,則為777 。這樣就可以透過兩種方式修改這個權限。
$ chmod a+rwx regular_file
或
$ chmod 777 regular_file
說明:
a指所用用戶,如果只想給用戶本身可讀可寫可執行權限,那麼可以把
a換成
u;而
+就是添加權限,相反的,如果想去掉某個權限,用
-,而
rwx則對應可讀、可寫入、可執行。更多用法見
chmod命令的幫助。
實際上除了這些權限外,還有兩個涉及安全方面的權限,即
setuid/setgid和唯讀控制等。
如果設定了檔案(程式或命令)的
setuid/setgid權限,那麼使用者將可用
root身份去執行該文件,因此,這將可能帶來安全隱患;如果設定了文件的唯讀權限,那麼用戶將僅僅對該文件將有可讀權限,這為避免諸如
rm -rf的「可惡」操作帶來一定的庇佑。
預設情況下,系統是不允許普通用戶執行
passwd命令的,透過
setuid/setgid,可以授權普通用戶執行它。
$ ls -l /usr/bin/passwd-rwx--x--x 1 root root 36092 2007-06-19 14:59 /usr/bin/passwd$ su #切換到root用戶,給程式或指令新增“黏著位」$ chmod +s /usr/bin/passwd$ ls -l /usr/bin/passwd-rws--s--x 1 root root 36092 2007-06-19 14:59 /usr/bin/passwd$ exit$ passwd #一般使用者透過執行指令,修改自己的密碼
說明:
setuid和setgid位是讓普通用戶可以以root使用者的角色運行只有root帳號才能運作的程式或指令。
雖然這在一定程度上為管理提供了方便,例如上面的操作讓普通用戶可以修改自己的帳號,而不是要
root帳號去為每個使用者做這些工作。關於
setuid/setgid的更多詳細解釋,請參考最後推薦的資料。
唯讀權限範例:為重要檔案加鎖(新增不可修改位元[immutable])),以避免各種誤操作帶來的災難性後果(例如
:``rm -rf)
$ chattr +i regular_file$ lsattr regular_file----i-------- regular_file$ rm regular_file #加immutable位後就無法對檔案進行任何「破壞性」的活動 rm: remove write-protected regular file `regular_file'? yrm: cannot remove `regular_file': Operation not permitted$ chattr -i regular_file #如果想對它進行常規操作,那麼可以把這個位元去掉$ rm regular_file
說明:
chattr可以用於設定檔案的特殊權限,更多用法請參考
chattr的幫助。
文件大小對於普通文件而言就是文件內容的大小,而目錄作為一個特殊的文件,它存放的內容是以目錄結構體組織的各類文件信息,所以目錄的大小一般都是固定的,它存放的檔案個數自然也就有上限,也就是它的大小除以檔案名稱的長度。設備檔案的「檔案大小」則對應設備的主、次設備號,而有名管道檔案因為特殊的讀寫性質,所以大小常是0 。硬連結(目錄檔案不能建立硬連結)實質上是原始檔案的一個完整的拷貝,因此,它的大小就是原始檔案的大小。而軟連結只是一個
inode,存放了一個指向原始文件的指針,因此它的大小只是原始文件名的位元組數。下面我們透過演示增加記憶。
原文件,連結文件文件大小的範例:
$ echo -n abcde > regular_file # 寫入5位元組$ ls -l regular_file*-rw-r--r-- 2 root root 5 2007-12-08 15:28 regular_file-rw-r--r -- 2 root root 5 2007-12-08 15:28 regular_file_hard_filelrwxrwxrwx 1 root root 12 2007-12-07 20:15 regular_file_soft_link -> regular_filelrwxrwxrwx 1 root root 22 2007-12-08 1wxrfile_ i=regular_file$ j=regular_file_soft_link$ echo ${#i} ${#j} #軟體連結存放的剛好是它們所指向的原始檔案的檔案名稱的位元組數12 22設備號對應的檔案大小:主、次設備號
$ ls -l hda1_block_dev_filebrw-r--r-- 1 root root 3, 1 2007-12-07 21:44 hda1_block_dev_file$ ls -l null_char_dev_filecrw-r--r-- 1 root root 1, 3 2007-13 2007 21:43 null_char_dev_file
補充:主
(major)、次(minor)設備號的作用有不同。當一個設備檔案被開啟時,核心會根據主設備號(
major number)去尋找在核心中已經以主設備號註冊的驅動程式(可以
cat /proc/devices查看已註冊的驅動號碼和主設備號碼的對應情況),而次設備號碼(
minor number)則是透過核心傳遞給了驅動本身(參考《The Linux Primer》第十章)。因此,對於核心而言,透過主設備號就可以找到對應的驅動去識別某個設備,而對於驅動而言,為了能夠更複雜地存取設備,例如存取設備的不同部分(如硬體透過分區分成不同部分,而出現
hda1,
hda2,
hda3等),例如產生不同要求的隨機數(如
/dev/random和
/dev/urandom等)。
目錄檔案的大小,為什麼是這樣?看看下面的目錄結構體的大小,目錄檔案的Block 中存放了該目錄下所有檔案名稱的入口。
$ ls -ld directory_file/drwxr-xr-x 2 root root 4096 2007-12-07 23:14 directory_file/
目錄的結構體如下:
struct dirent { long d_ino; off_t d_off; unsigned short d_reclen; char d_name[NAME_MAX+1]; /* 檔案名稱*/}文件的時間屬性可以記錄使用者對文件的操作信息,在系統管理、判斷文件版本信息等情況下將為管理員提供參考。因此,在閱讀文件時,建議使用
cat等閱讀工具,不要用編輯工具
vim去閱讀,因為即使沒有做任何修改操作,一旦執行了保存命令,將修改檔案的時間戳資訊。
檔案名稱並沒有存放在檔案結構體內,而是存放在它所在的目錄結構體中。所以,在目錄的同一層級中,檔案名稱必須是唯一的。
對於文件,常見的操作包括建立、刪除、修改、讀取、寫入等。關於各種操作對應的「背後動作」將在下一章《Shell編程範例之檔案系統操作》詳細分析。
socket文件是一類特殊的文件,可以透過C 語言創建,這裡不做介紹(暫時不知道是否可以用命令直接創建),其他文件將透過命令創建。
$ touch regular_file #建立普通文件$ mkdir directory_file #建立目錄文件,目錄文件裡頭可以包含更多文件$ ln regular_file regular_file_hard_link #硬鏈接,是原文件的一個完整拷貝比$ ln -s regular_file regular_file_soft_link #類似一個文件指針,指向原始檔案$ mkfifo fifo_pipe #或透過mknod fifo_pipe p 來創建,FIFO滿足先進先出的特點$ mknod hda1_block_dev_file b 3 1 #塊設備$ mknod null_char_dev_file c 1 3 #字元設備
建立一個檔案實際上是在檔案系統中新增了一個節點(
inode),此節點資訊將會保存到檔案系統的節點表中。更形像地說,就是在一顆樹上長了一顆新的葉子(文件)或枝條(目錄文件,上面還可以長葉子的那種),這些可以通過tree
命令或者ls` 命令形像地呈現出來。文件系統從日常使用的角度,完全可以當成一顆倒立的樹來看,因為它們太像了,太容易記憶。
$ tree 目前目錄
或者
$ ls 目前目錄
刪除檔案最直接的印像是這個檔案再也不存在了,這同樣可以透過
ls或者
tree命令呈現出來,就像樹木被砍掉一個分支或摘掉一片葉子一樣。實際上,在這些文件刪除之後,並不是立即消失了,而是僅僅做了刪除標記,因此,如果刪除之後,沒有相關的磁碟寫操作把相應的磁碟空間“覆蓋”,那麼原理上是可以恢復的(雖然如此,但是這樣的工作往往很麻煩,所以在刪除一些重要資料時,請務必三思而後行,例如做好備份工作),相應的做法可以參考後續資料。
具體刪除檔案的命令有
rm,如果要刪除空目錄,可以用
rmdir命令。例如:
$ rm regular_file$ rmdir directory_file$ rm -r directory_file_not_empty
rm有兩個非常重要的參數,一個是
-f,這個命令是非常“野蠻的”,它估計給很多Linux user 帶來了痛苦,另一個是
-i,這個命令是非常“溫柔的”,它估計讓很多用戶感覺煩躁不已。用哪一個還是根據您的「心情」吧,如果做好了充分的備份工作,或者採取了一些有效避免災難性後果的動作的話,您在做這些工作的時候就可以放心一些啦。
文件的複製通常是指文件內容的「暫時」複製。透過這一節開頭的介紹,我們應該了解到,文件的硬鏈接和軟鏈接在某種意義上說也是“文件的複製”,前者同步複製文件內容,後者在讀寫的情況下同步“複製”文件內容。例如:
用
cp命令常規地複製檔案(複製目錄需要
-r選項)
$ cp regular_file regular_file_copy$ cp -r diretory_file directory_file_copy
建立硬連結(
link和
copy不同之處是後者是同步更新,前者則不然,複製之後兩者不再相關)
$ ln regular_file regular_file_hard_link
建立軟連結
$ ln -s regular_file regluar_file_soft_link
修改檔案名稱實際上僅僅修改了檔案名稱識別碼。可以透過
mv命令來實現修改檔名操作(即重命名)。
$ mv regular_file regular_file_new_name
編輯檔案其實是操作檔案的內容,對應到普通文字檔案的編輯,這裡主要涉及到檔案內容的讀取、寫入、追加、刪除等。這些工作通常會透過專門的編輯器來做,這類編輯器有命令列下的
vim、
emacs和圖形介面下的
gedit,kedit等。如果是一些特定的文件,會有專門的編輯和處理工具,例如影像處理軟體
gimp,文件編輯軟體
OpenOffice等。這些工具一般都會有專門的教學。
以下主要簡單介紹Linux 下透過重定向來實現檔案的這些常規的編輯操作。
建立一個文件並寫入
abcde
$ echo abcde > new_regular_file
再往上面的文件中追加一行
abcde
$ echo abcde >> new_regular_file
按行讀一個文件
$ while read LINE; do echo $LINE; done < test.sh
提示:如果要把包含重定向的字串變數當作指令來執行,請使用
eval命令,否則無法解釋重定向。例如,
$ redirect=echo abcde >test_redirect_file$ $redirect #這裡會把>當作字元> 印出來,而不會當作重定向解釋abcde >test_redirect_file$ eval $redirect #這樣才會把> 解釋成重定向$ cat test_redirect_fileabcde
壓縮和解壓縮檔案在某個意義上來說是為了方便檔案內容的傳輸,不過也可能有一些特定的用途,例如核心和檔案系統的映像檔等(更多相關的知識請參考後續資料)。
這裡僅介紹幾種常見的壓縮和解壓縮方法:
tar
$ tar -cf file.tar file #壓縮$ tar -xf file.tar #解壓縮
gz
$ gzip -9 file$ gunzip file
tar.gz
$ tar -zcf file.tar.gz file$ tar -zxf file.tar.gz
bz2
$ bzip2 file$ bunzip2 file
tar.bz2
$ tar -jcf file.tar.bz2 file$ tar -jxf file.tar.bz2
透過上面的演示,應該已經非常清楚
tar,
bzip2,bunzip2,
gzip,gunzip
命令的角色了吧?如果還不清楚,請多操作和比較一些上面的命令,並查看它們的手冊:man tar`...
文件搜尋是指在某個目錄層次中找出具有某些屬性的檔案在檔案系統中的位置,這個位置如果擴展到整個網絡,那麼可以表示為一個
URL地址,對於本地的地址,可以表示為
file://+本地路徑。本地路徑在Linux 系統下是以
/開頭,例如,每個使用者的家目錄可以表示為:
file:///home/。以下僅介紹本地文件搜尋的一些辦法。
find命令提供了一種「及時的」搜尋辦法,它根據使用者的請求,在指定的目錄層次中遍歷所有檔案直到找到需要的檔案為止。而
updatedb+locate提供了一種「快速的」的搜尋策略,
updatedb更新並產生一個本地文件資料庫,而
locate透過檔案名稱檢索這個資料庫以便快速找到對應的檔案。前者支援透過各種文件屬性進行搜索,並且提供了一個介面(
-exec選項)用於處理搜尋後的文件。因此為「單一指令」腳本的愛好者提供了極大的方便,不過對於根據檔案名稱的搜尋而言,
updatedb+locate的方式在搜尋效率上會有明顯提高。以下簡單介紹這兩種方法:
find命令基本使用演示
$ find ./ -name *.c -o -name *.h #找出所有的C語言文件,-o是或$ find ./ ( -name *.c -o -name *.h ) - exec mv '{}' ./c_files/ ;# 把找到的檔案移到c_files下,這種用法非常有趣上面的用法可以用
xargs命令替代
$ find ./ -name *.c -o -name *.h | xargs -i mv '{}' ./c_files/# 如果要對檔案做更複雜的操作,可以考慮把mv改寫為自己的處理命令,例如,我需要修改所有的檔名後綴為大寫。
$ find ./ -name *.c -o -name *.h | xargs -i ./toupper.sh '{}' ./c_files/toupper.sh就是我們需要實現的轉換小寫為大寫的一個處理文件,具體實現如下:
$ cat toupper.sh#!/bin/bash# the {} will be expended to the current line and becomen the first argument of this scriptFROM=$1BASENAME=${FROM##*/}BASE=${BASENAME%.* }SUFFIX=${BASENAME##*.}TOSUFFIX=$(echo $SUFFIX | tr '[az]' '[AZ]')TO=$2/$BASE.$TOSUFFIXCOM=mv $FROM $TOecho $COMeval $COMupdatedb+locate基本使用演示
$ updatedb #更新庫$ locate find*.gz #尋找包含find字串的所有gz壓縮包
實際上,除了上面兩種命令外,Linux 下還有命令查找工具:
which和
whereis,前者用於返回某個命令的全路徑,而後者用於返回某個命令、來源檔案、
man 檔案的路徑。例如,尋找find` 指令的絕對路徑:
$ which find/usr/bin/find$ whereis findfind: /usr/bin/find /usr/X11R6/bin/find /usr/bin/X11/find /usr/X11/bin/find /usr/man/man1/ find.1.gz /usr/share/man/man1/find.1.gz /usr/X11/man/man1/find.1.gz
需要提到的是,如果想根據文件的內容搜尋文件,那麼
find和
updatedb+locate以及
which,
whereis都無能為力啦,可選的方法是
grep,
sed等命令,前者在加上
-r參數以後可以在指定目錄下檔案中搜尋指定的檔案內容,後者再使用
-i參數後,可以對文件內容進行替換。它們的基本用法在前面的章節中已經詳細介紹了,這裡就不再贅述。
值得強調的是,這些命令對文件的操作非常有意義。它們在某個程度上把文件系統結構給抽象了,使得對整個文件系統的操作簡化為對單個文件的操作,而單個文件如果僅僅考慮文本部分,那麼最終卻轉化成了之前的字符串操作,即上一節討論過的內容。為了更清楚了解文件的組織結構,文件之間的關係,在下一節將深入探討文件系統。
從檔案I/O 看Linux 的虛擬檔案系統
Linux 檔案系統剖析
《Linux 核心》第九章檔案系統
Linux Device Drivers, 3rd Edition
技巧:Linux I/O 重定向的一些小技巧
Intel 平台下Linux 中ELF 檔案動態連結的載入、解析及實例分析:
part1,
part2
Shell 腳本偵錯技術
ELF 檔案格式及程式載入執行過程總匯
Linux下C 語言程式設計-檔案的操作
Linux下C 語言程式設計的檔案操作部分
Filesystem Hierarchy Standard
學會恢復Linux系統裡被刪除的Ext3 文件
使用mc恢復被刪除文件
linux ext3 誤刪除及復原原理
Linux壓縮/解壓縮方式大全
Everything is a byte
考慮到檔案和檔案系統的重要性,將把它分成三個小節來介紹:檔案、檔案系統、程式與流程。在「文件」這一部分,主要介紹文件的基本屬性和常規操作,在「文件系統」那部分,將深入探討Linux 文件系統的各個部分(包括Linux 文件系統的結構、具體某個文件系統的大體結構分析、底層驅動的工作原理),在「程式與進程」一節將專門討論可執行檔的相關內容(包括不同的程式類型、載入執行過程、不同進程之間的互動[命令管道和無名管道、訊號通訊]、對進程的控制等)
有必要討論清楚目錄大小的含義,另外,最好把一些常規的文件操作全部考慮到,包括文件的讀、寫、執行、刪除、修改、複製、壓縮/解壓縮等
下午剛從上海回來,比賽結果很“糟糕”,不過到現在已經不重要了,關鍵是通過決賽發現了很多不足,發現了設計在系統開發中的關鍵角色,並且發現了上海是個美麗的城市,交也是一所美麗的大學。回來就開始整理這個因為比賽落下了兩週的Blog
12月15日,新增文件搜尋部分內容