Python相当于find2perl

时间:2011-09-24 20:56:09

标签: python find os.walk

Perl有一个名为find2perl的可爱小实用程序,它将(非常忠实地)将Unix find实用程序的命令行转换为Perl脚本来执行相同操作。

如果你有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

它找到以share

下面的/usr结尾的所有目录

现在运行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中以相同的方式执行它对我来说非常重要。

那么可以用于Python的等效find2perl吗?到目前为止,我刚刚使用find2perl,然后手动翻译Perl代码。这很难,因为Perl文件测试操作符有时比os.path中的Python文件测试different

4 个答案:

答案 0 :(得分:4)

如果您尝试重新实现所有find,那么是的,您的代码将变得毛茸茸。 find本身就很毛茸茸。

但在大多数情况下,您并不是要尝试复制查找的完整行为;你正在执行一个更简单的任务(例如,“找到以.txt结尾的所有文件”)。如果您确实需要全部find,只需运行find并阅读输出。正如你所说,这是黄金标准;你也可以使用它。

我经常编写代码来读取stdin上的路径,所以我可以这样做:

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

答案 1 :(得分:2)

有几个观察点和几段代码可以帮助您。

首先,Python可以像Perl一样执行这种形式的代码:

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

find2perl是一个聪明的代码模板,它基于find模板发出Perl函数。因此,复制此模板,您将不会感知到“数百个排列”。

其次,find2perl的结果不是完美,因为find版本之间可能存在差异,例如GNU或BSD。

第三,默认情况下,os.walk是自下而上的; find是自上而下的。如果底层目录树在递归时发生变化,则会产生不同的结果。

Python中有两个可以帮助您的项目:twanderdupfinder。每个都努力与os无关,每个都像find一样递归文件系统。

如果您在Python中模拟一般的find类似函数,请将os.walk设置为自上而下,使用glob来复制shell扩展,并使用您在这两个项目中找到的一些代码,你可以毫不费力地复制find2perl

抱歉,我无法指出可以满足您需求的东西......

答案 2 :(得分:1)

我认为glob可以帮助您实现此目标。

答案 3 :(得分:1)

我编写了一个Python脚本,使用os.walk()进行搜索和替换;在写这样的东西之前看一下这可能是有用的。

Replace strings in files by Python

而find(1)的任何Python替代品都将严重依赖os.stat()来检查文件的各种属性。例如,有一些标志要查找(1)检查文件大小或上次修改的时间戳。