2011-09-24 62 views
14

Perl有一個可愛的小實用程序,名爲find2perl,它可以將(非常忠實地)將Unix find實用程序的命令行轉換爲Perl腳本來執行相同操作。Python的等價物find2perl

如果你有一個find命令是這樣的:

find /usr -xdev -type d -name '*share' 

         ^^^^^^^^^^^^ => name with shell expansion of '*share' 
       ^^^^ => Directory (not a file) 
      ^^^ => Do not go to external file systems 
    ^^^ => the /usr directory (could be multiple directories 

它發現下面/usr

share結束現在運行find2perl /usr -xdev -type d -name '*share'的所有目錄,它會發出一個Perl腳本做同樣的。然後您可以修改腳本以供您使用。

Python有os.walk()它肯定有所需的功能,遞歸目錄列表,但有很大的不同。

find . -type f -print的簡單例子查找並打印當前目錄下的所有文件。使用os.walk()天真的實現是:

for path, dirs, files in os.walk(root): 
    if files: 
     for file in files: 
      print os.path.join(path,file) 

但是,這會產生不同的結果比在shell中鍵入find . -type f -print

我也一直在測試各種os.walk()循環對:

# create pipe to 'find' with the commands with arg of 'root' 
find_cmd='find %s -type f' % root 
args=shlex.split(find_cmd) 
p=subprocess.Popen(args,stdout=subprocess.PIPE) 
out,err=p.communicate()  
out=out.rstrip()   # remove terminating \n 
for line in out.splitlines() 
    print line 

不同的是,os.walk()計算鏈接作爲文件;找到這些跳過。

所以正確的實現,是一樣的file . -type f -print變爲:

for path, dirs, files in os.walk(root): 
    if files: 
     for file in files: 
      p=os.path.join(path,file) 
      if os.path.isfile(p) and not os.path.islink(p): 
       print(p) 

由於有上百找到初選和不同的副作用的排列,這成爲耗費時間來測試每一個變種。由於find是POSIX世界中關於如何計算樹中的文件的黃金標準,因此在Python中執行相同的操作對我來說很重要。

那麼是否有相當於find2perl可用於Python?到目前爲止,我剛剛使用find2perl,然後手動翻譯Perl代碼。這很難,因爲Perl文件測試運算符有時比在os.path中測試Python文件的測試運算符是different

+0

我建議部分答案可以在這裏找到:http://stackoverflow.com/questions/4639506/os- walk-with-regex對不起,我不知道find/find2perl足以幫助更多。 *(也可能是http://stackoverflow.com/questions/5141437/filtering-os-walk-dirs-and-files)* –

回答

2

有幾個意見和幾段代碼可以幫助你。

首先,Python可以以這種形式就像Perl中執行代碼:

cat code.py | python | the rest of the pipe story... 

find2perl是其基於發現的模板的Perl函數一個聰明的代碼模板。因此,複製這個模板,你就不會有你感覺到的「數百個排列組合」。

其次,從find2perl結果並不完美就像有可能找到的版本,如GNU或BSD之間的差異。

三,默認情況下,os.walk是自下而上的; find是自上而下的。如果在緩衝它時您的基礎目錄樹正在更改,這會產生不同的結果。

Python中有兩個項目可以幫助您:twanderdupfinder。每個都努力獨立於操作系統,並且每個都像find一樣遞歸文件系統。

如果模板一般find如同在Python功能,設置os.walk遞歸自上而下,使用水珠複製外殼擴展,並使用一些您在這兩個項目中發現的代碼,你可以複製find2perl沒有太多困難。

抱歉,我不能指向東西準備去滿足您的需求...

4

如果你想重新實現所有的find,那麼是的,你的代碼會變得毛茸茸的。 find本身就非常有毛。

但是,在大多數情況下,您並未嘗試複製find的完整行爲;您正在執行更簡單的任務(例如,「查找所有以.txt結尾的文件」)。如果你真的需要所有的find,只需運行find並讀取輸出。正如你所說,這是金標準;你不妨使用它。

我經常編寫代碼,上stdin讀取路徑,這樣我可以這樣做:

find ...a bunch of filters... | my_python_code.py 
+1

這隻適用於你的目標程序環境在Unix上的假設。 'find2perl'的優點是你可以在Unix上編寫一些東西,並在Perl運行的任何地方運行 - 例如在Windows上。 –

1

我覺得glob可以在你執行這方面的幫助。

1

我寫了一個Python腳本來使用os.walk()來搜索和替換;在寫這樣的東西之前先看看它可能是一件有用的事情。

Replace strings in files by Python

而且任何的Python替代的發現(1)將在很大程度上依賴於os.stat()來檢查文件的各種屬性。例如,有一些標誌可以找到(1)檢查文件的大小或上次修改的時間戳。