2011-09-24 20 views
14

Perl tiene una utilidad muy pequeña llamada find2perl que traducirá (bastante fielmente) una línea de comandos para la utilidad Unix find en una secuencia de comandos Perl para hacer lo mismo.Python equivalente a find2perl

Si usted tiene un comando find así:

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 

Se encuentra todos los directorios que terminan en share continuación /usr

Ahora ejecute find2perl /usr -xdev -type d -name '*share' y se emitirá un script en Perl para hacer lo mismo. A continuación, puede modificar el script para su uso.

Python tiene os.walk() que ciertamente tiene la funcionalidad necesaria, directorio recursivo listado, pero hay grandes diferencias.

Tome el caso simple de find . -type f -print para encontrar e imprimir todos los archivos en el directorio actual. Una implementación ingenua usando os.walk() sería:

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

Sin embargo, esto producirá resultados diferentes de escribir find . -type f -print en la cáscara.

También he estado probando diferentes os.walk() bucles en contra:

# 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 

La diferencia es que os.walk() cuenta enlaces como archivos; encontrar omite estos.

Así que una aplicación correcta de que es el mismo que se convierte en 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) 

Puesto que hay cientos de permutaciones de encontrar las primarias y diferentes efectos secundarios, esto se convierte en mucho tiempo para probar todas las variantes. Dado que find es el estándar de oro en el mundo POSIX sobre cómo contar archivos en un árbol, hacerlo de la misma manera en Python es importante para mí.

¿Existe un equivalente de find2perl que se pueda utilizar para Python? Hasta ahora he estado usando find2perl y luego traduciendo manualmente el código de Perl. Esto es difícil porque los operadores de prueba de archivos Perl son different que las pruebas del archivo Python en os.path a veces.

+0

yo sugeriría parte de la respuesta se puede conocer aquí: http://stackoverflow.com/questions/4639506/os- walk-with-regex Lo siento, no sé find/find2perl suficiente para ayudar más. * (quizás también http://stackoverflow.com/questions/5141437/filtering-os-walk-dirs-and-files)* –

Respuesta

2

Hay un par de observaciones y varias piezas de código para ayudarlo en su camino.

En primer lugar, Python puede ejecutar código en esta forma como Perl:

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

find2perl es una plantilla de código inteligente que emite una función Perl basado en una plantilla de hallazgo. Por lo tanto, replique esta plantilla y no tendrá los "cientos de permutaciones" que está percibiendo.

En segundo lugar, los resultados de find2perl no son perfectos al igual que existen potencialmente diferencias entre las versiones de encontrar, tales como GNU o BSD.

En tercer lugar, de forma predeterminada, os.walk es de abajo hacia arriba; find es de arriba hacia abajo. Esto genera resultados diferentes si su árbol de directorios subyacente está cambiando mientras lo vuelve a generar.

Existen dos proyectos en Python que pueden ayudarle: twander y dupfinder. Cada uno intenta ser independiente del sistema y cada uno recurre al sistema de archivos como find.

Si plantilla de un general find como función en Python, establezca os.walk a recursiva de arriba hacia abajo, glob uso de replicar el desarrollo del forro, y el uso de algunos de los códigos que se encuentran en esos dos proyectos, puede replicar find2perl sin demasiado dificultad.

Siento no haber podido apuntar a algo listo para ir a sus necesidades ...

4

Si está tratando de volver a implementar todos find, entonces sí, su código va a ponerse peludo. find es bastante peludo por sí mismo.

En la mayoría de los casos, sin embargo, no está tratando de replicar el comportamiento completo de find; está realizando una tarea mucho más simple (por ejemplo, "buscar todos los archivos que terminan en .txt"). Si realmente necesita todos find, simplemente ejecute find y lea la salida. Como dices, es el estándar de oro; también podrías usarlo.

A menudo escribo código que lee caminos en stdin sólo para poder hacer esto:

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

Esto solo funciona bajo la suposición de que el entorno del programa de destino está en Unix tho. La belleza de 'find2perl' es que puede escribir algo en Unix y ejecutarlo en cualquier lugar que ejecute Perl, en Windows, por ejemplo. –

1

creo glob podría ayudar en su implementación de este.

1

Escribí un script de Python para usar os.walk() para buscar y reemplazar; podría ser una cosa útil para mirar antes de escribir algo como esto.

Replace strings in files by Python

Y cualquier reemplazo de Python para find (1) va a depender en gran medida de os.stat() para comprobar varias propiedades del archivo. Por ejemplo, hay indicadores para encontrar (1) que verifican el tamaño del archivo o la última marca de tiempo modificada.