Ubuntu

當使用 locate 和 find 計算源文件和 LOC 時 - 為什麼 Python 文件會出現不同?

  • October 29, 2017

我無法理解為什麼CfindlocatePython 源文件的工作方式會有所不同。我的目標是計算給定語言的源文件數量及其原始碼行的總和。我同時使用findlocate來比較輸出(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 下同樣奇怪的結果

我使用 執行updatedbsudo但我以普通使用者身份執行所有這些命令。

你的命令有很多問題。

首先,如果您在不包含任何名稱匹配的文件的目錄中執行它,則locate *.c僅查找匹配的文件。否則,shell 會擴展為匹配文件的列表。這可能不會發生,否則你會得到更少的匹配,但是像這樣留下未引用的 glob 是一個壞習慣,因為它有一天會咬你。(這是該網站上的一個常見話題。). 相反,寫*.c``*.c``*.c``find -name *.c

locate '*.c' …
find / -name '*.c' …

或類似的東西。

有一些常見的原因locatefind可能會給出不同的結果。它們似乎不適用於您的情況,因為您獲得了相同數量的點擊,但這再次是您需要注意的事情。

  • 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/scripttemplate(dev).pywc現在應該清楚錯誤消息的原因。

有幾種解決方案。一種是對findand使用空分隔格式xargs。這適用於任何文件名,甚至是包含換行符的文件名(允許,但不常見)。

find / -name '*.py' -print0 | xargs -0 wc -l | tail -3

另一個是忘記問題xargsfind直接呼叫命令。

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}'

引用自:https://unix.stackexchange.com/questions/400980