linux find命令中-print0和xargs中-0的用法

1、默認情況下, find命令每輸出一個文件名, 後面都會接着輸出一個換行符 ('\n'), 因此find 的輸出都是一行一行的:

 [bash-4.1.5] ls -l
  total 0
  -rw-r--r-- 1 root root 0 2010-08-02 18:09 file1.log
  -rw-r--r-- 1 root root 0 2010-08-02 18:09 file2.log
[bash-4.1.5] find . -name '*.log'
  ./file2.log
  ./file1.log

比如用find命令把所有的 .log 文件刪掉, 可以這樣配合 xargs 一起用:

[bash-4.1.5] find . -name '*.log' | xargs rm

find命令結合xargs 真的很強大,然而:  

[bash-4.1.5] touch "file 1.log"
[bash-4.1.5] touch "file 2.log"

[bash-4.1.5] ls -l
total 0
-rw-r--r-- 1 root root 0 2010-08-02 18:12 file 1.log
-rw-r--r-- 1 root root 0 2010-08-02 18:12 file 2.log
[bash-4.1.5] find -name '*.log'
./file 1.log
./file 2.log
[bash-4.1.5] find -name '*.log' | xargs rm
rm: cannot remove `./file': No such file or directory
rm: cannot remove `1.log': No such file or directory
rm: cannot remove `./file': No such file or directory
rm: cannot remove `2.log': No such file or directory

原因其實很簡單, xargs 默認是以空白字符 (空格, TAB, 換行符) 來分割記錄的, 因此文件名 ./file 1.log 被解釋成了兩個記錄 ./file 和 1.log, 不幸的是 rm 找不到這兩個文件. 如下:

爲了解決此類問題, 讓 find命令在打印出一個文件名之後接着輸出一個 NULL 字符 ('') 而不是換行符 (-print0), 然後再告訴 xargs 也用 NULL 字符來作爲記錄的分隔符 (xargs -0). 這就是 find 的 -print0 和 xargs 的 -0 的來歷吧。

[bash-4.1.5] find -name '*.log' -print0 | hd           // 這裏沒看太懂,看懂的人請留言指教。
0 1 2 3 4 5 6 7 8 9 A B C D E F |0123456789ABCDEF|
--------+--+--+--+--+---+--+--+--+---+--+--+--+---+--+--+--+--+----------------|
00000000: 2e 2f 66 69 6c 65 20 31 2e 6c 6f 67 00 2e 2f 66 |./file 1.log../f|
00000010: 69 6c 65 20 32 2e 6c 6f 67 00 |ile 2.log. |
[bash-4.1.5] find -name '*.log' -print0 | xargs -0 rm
[bash-4.1.5] find -name '*.log'

你可能要問了,爲什麼要選 '' 而不是其他字符做分隔符呢? 這個也容易理解: 一般的編程語言中都用 '' 來作爲字符串的結束標誌, 文件的路徑名中不可能包含 '' 字符。

解釋下爲什麼 find -name '*.log' -print0 | xargs -0 rm 能刪除:

先看 find -name '*.log' -print 的結果:

在看先看 find -name '*.log' -print0 的結果如下,可以發現換行符變成了 ''

 

然後看一下  find -name '*.log' -print0 | xargs -0 的輸出結果:發現 xargs 將 ' ' 當作多條記錄的分割符。

因此 file 1.log 和 file 2.log 就被分開處理了, file 1.log 會被作爲一個文件處理,file 1.log就不會被拆開爲 file 和 1.log 兩個文件了。

  

 至於爲什麼  file 1.log 和 file 2.log 會被分開處理,詳情看上一篇文章。

 

find -print 和 -print0的區別

man find的結果如下:

-print 在每一個輸出後會添加一個回車換行符,而-print0則不會。
[root@AaronWong shell_test]# find /home/AaronWong/ABC/ -type l -print
/home/AaronWong/ABC/libcvaux.so
/home/AaronWong/ABC/libgomp.so.1
/home/AaronWong/ABC/libcvaux.so.4
/home/AaronWong/ABC/libcv.so
/home/AaronWong/ABC/libhighgui.so.4
/home/AaronWong/ABC/libcxcore.so
/home/AaronWong/ABC/libhighgui.so
/home/AaronWong/ABC/libcxcore.so.4
/home/AaronWong/ABC/libcv.so.4
/home/AaronWong/ABC/libgomp.so
/home/AaronWong/ABC/libz.so
/home/AaronWong/ABC/libz.so.1
[root@AaronWong shell_test]# find /home/AaronWong/ABC/ -type l -print0
/home/AaronWong/ABC/libcvaux.so/home/AaronWong/ABC/libgomp.so.1/home/AaronWong/ABC/libcvaux.so.4/home/AaronWong/ABC/libcv.so/home/AaronWong/ABC/libhighgui.so.4/home/AaronWong/ABC/libcxcore.so/home/AaronWong/ABC/libhighgui.so/home/AaronWong/ABC/libcxcore.so.4/home/AaronWong/ABC/libcv.so.4/home/AaronWong/ABC/libgomp.so/home/AaronWong/ABC/libz.so/home/AaronWong/ABC/libz.so.1
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章