當使用 locate 和 find 計算源文件和 LOC 時 - 為什麼 Python 文件會出現不同?
我無法理解為什麼C
find
和locate
Python 源文件的工作方式會有所不同。我的目標是計算給定語言的源文件數量及其原始碼行的總和。我同時使用find
和locate
來比較輸出(updatedb
在此之前執行以sudo
確保locate
報告目前結果)。對於 C 文件,這按預期工作,源文件的數量是相同的
$ find / -name *.c |& grep -v "Permission denied" | wc -l 1056 $ locate *.c | wc -l 1056
使用
xargs
,原始碼行的總和也相同。$ locate *.c | xargs wc -l | tail -3 138 /usr/src/kernels/3.10.0-693.el7.ppc64/scripts/selinux/genheaders/genheaders.c 147 /usr/src/kernels/3.10.0-693.el7.ppc64/scripts/selinux/mdp/mdp.c 705376 total $ find / -name *.c |& grep -v "Permission denied" | xargs wc -l | tail -3 2994 /opt/Python-3.6.2/Objects/listobject.c 821 /opt/Python-3.6.2/Objects/bytes_methods.c 705376 total
只是為了測試,這也適用於具有
.java
副檔名的文件 - 我得到了相同的一致結果。但是,當我對 Python 文件(即.py
副檔名)重複相同的操作時源文件編號匹配。
$ find / -name *.py |& grep -v "Permission denied" | wc -l 9249 $ locate *.py | wc -l 9249
但是 Python 文件的程式碼行總和給出了非常不同的結果。
$ locate *.py | xargs wc -l | tail -3 wc: /usr/lib/python2.7/site-packages/setuptools/script: No such file or directory wc: template: No such file or directory wc: (dev).py: No such file or directory wc: /usr/lib/python2.7/site-packages/setuptools/script: No such file or directory wc: template.py: No such file or directory 220 /usr/src/kernels/3.10.0-693.el7.ppc64/scripts/rt-tester/rt-tester.py 129 /usr/src/kernels/3.10.0-693.el7.ppc64/scripts/tracing/draw_functrace.py 753350 total $ find / -name *.py |& grep -v "Permission denied" | xargs wc -l | tail -3 wc: /usr/lib/python2.7/site-packages/setuptools/script: No such file or directory wc: template: No such file or directory wc: (dev).py: No such file or directory wc: /usr/lib/python2.7/site-packages/setuptools/script: No such file or directory wc: template.py: No such file or directory 1919 /opt/Python-3.6.2/python-gdb.py 69 /opt/Python-3.6.2/python-config.py 1034101 total
有人可以解釋為什麼會這樣嗎?Python 文件有什麼不同(我不敢相信它與文件類型有關,但我很難過)。我在這裡想念什麼?
在 Ubuntu 和 RH 下同樣奇怪的結果
我使用 執行
updatedb
,sudo
但我以普通使用者身份執行所有這些命令。
你的命令有很多問題。
首先,如果您在不包含任何名稱匹配的文件的目錄中執行它,則
locate *.c
僅查找匹配的文件。否則,shell 會擴展為匹配文件的列表。這可能不會發生,否則你會得到更少的匹配,但是像這樣留下未引用的 glob 是一個壞習慣,因為它有一天會咬你。(這是該網站上的一個常見話題。). 相反,寫*.c``*.c``*.c``find -name *.c
locate '*.c' … find / -name '*.c' …
或類似的東西。
有一些常見的原因
locate
,find
可能會給出不同的結果。它們似乎不適用於您的情況,因為您獲得了相同數量的點擊,但這再次是您需要注意的事情。
locate
結果從上次執行的updatedb
. 這通常在晚上執行一次。find
每次執行命令時計算的結果。- 根據系統、
locate
您擁有的實現以及配置方式,它可能只讓您看到可公開訪問的文件(例如 GNU findutils,而不是 mlocate 或 slocate),或者它可能會近似於您正在使用的文件允許訪問(例如,因為涉及 Linux 安全模組的複雜設置會區分嘗試訪問文件的應用程序)。- 模式的 to和 to
*SUFFIX
含義相同(假設不包含斜杠或萬用字元),但其他模式不包含。例如等於,不等於。locate``find -name``SUFFIX``locate foo``find / -name '*foo*'``find / -name 'foo'
可能但可能不會導致問題的另一件事是您已將錯誤消息從管道傳輸
find
到命令的數據處理部分。您刪除包含 的行Permission denied
,這會導致您錯過包含此名稱的文件(好吧,您可能沒有),並導致任何不包含Permission denied
的錯誤消息被解釋為輸入行。將數據輸出與錯誤輸出混合在一起很少是一個好主意,而且在這裡很荒謬。如果您想忽略錯誤,請將它們重定向到/dev/null
:find … 2>/dev/null | …
絕對讓您感到痛苦的是,它
xargs
期望輸入語法與find
產生的語法不同。在 的輸入中xargs
,任何空格都會分隔項目,而不僅僅是換行符。這三個字元\'"
也是專門解析的。空格在文件名中很常見,除了/
空字節之外,所有其他字元都是允許的。xargs
接收作為輸入的行之一是/usr/lib/python2.7/site-packages/setuptools/script template (dev).py
對於
xargs
,這是三個項目/usr/lib/python2.7/site-packages/setuptools/script
:template
和(dev).py
。wc
現在應該清楚錯誤消息的原因。有幾種解決方案。一種是對
find
and使用空分隔格式xargs
。這適用於任何文件名,甚至是包含換行符的文件名(允許,但不常見)。find / -name '*.py' -print0 | xargs -0 wc -l | tail -3
另一個是忘記問題
xargs
並find
直接呼叫命令。find / -name '*.py' -exec wc -l {} + | tail -3
第一個解決方案可能適用於您的
locate
實施,請檢查它是否有-0
選項。第二種解決方案特定於find
. 如果您對 的換行分隔輸出感到困惑locate
,並且您擁有 GNU 版本xargs
,那麼您可以使用-d '\n'
它來將輸入解析為換行分隔,而無需任何形式的引用。locate '*.py' | xargs -d '\n' wc -l | tail -3
這是你的主要問題。另一個問題是命令行有最大長度。
xargs
命令(或 的-exec … {} +
操作)在find
命令行上放置盡可能多的文件名,如果它們不適合,則命令(此處為wc -l
)會執行多次,每批文件執行一次。使用tail -3
,您只能看到最後兩個文件和最後一批的總數(假設最後一批中至少有兩個文件)。先前批次中的文件不會反映在此輸出中。由於find
並且locate
可能不會以相同的順序報告文件,因此您可能會看到不同的結果。如何解決最大長度問題取決於您要對數據做什麼。如果您想要的只是總計,那麼一種方法(假設文件名中沒有換行符)是計算所有
total
行。… | xargs -d '\n' wc -l | awk '/^[0-9]+\ttotal$/ {total += $1} END {print total}'