Usar find before wc elimina el total

2

Estoy usando find para buscar en todos los subdirectorios y el directorio actual para encontrar todos los archivos .py, y luego ejecuto wc -l para encontrar el número de líneas. Sin embargo, cuando uso find con wc, el campo Total se deja, a diferencia de cuando ejecuto wc solo. ¿Alguien sabe por qué ocurre esto?

find . -name \*.py -exec wc -l {} \;
  187 ./check.py
   43 ./file.py
   33 ./mitch.py
       ...
 1014 ./serve.py
   41 ./test_scripts/line_graph.py
   39 ./welcome.py

Pero no total, pero cuando ejecuto wc -l *.pyen un directorio obtengo un total:

wc -l *.py
 187 check.py
  43 file.py
  94 log_com.py
 154 log_results.py
  33 mitch.py
1014 serve.py
  39 welcome.py
1564 total
taronish4
fuente

Respuestas:

1

wcsolo genera un valor Total cuando se llama con más de un archivo como argumentos.

Del manual de GNU :

Si se proporciona más de un archivo, wcimprime una línea final que contiene los recuentos acumulativos, con el nombre del archivo total.

En su caso, no puede obtener una salida Total , ya que invoca wcuna vez por cada archivo encontrado, por lo que cada wcllamada posterior no sabe sobre la anterior.


Si aún desea el recuento total, puede usar la globstaropción en Bash para recurrir a directorios y .pyarchivos de lista :

shopt -s globstar
wc -l **/*.py

O, como sugiere Grawity, con findla -exec command {} +opción de GNU , findsustituir todas las rutas encontradas, en {}lugar de llamar a cada una individualmente (aunque existe un límite en la cantidad de archivos que puede sustituir, al igual que con el enfoque global).

slhck
fuente
Ah eso tiene sentido. Entonces, ¿cómo voy a hacer esto en su lugar?
taronish4
Actualicé mi publicación. La forma más a prueba de balas sería usar awk: ver la respuesta de Grawity.
slhck
1

No hay totalcampo porque solo hay un archivo.

Con la acción, ejecuta el comando una vez para cada archivo , con solo un argumento agregado cada vez. Por lo tanto, no hay nada de lo que cada invocación pueda calcular el total.-exec command {} ;find wc

Tendrías que usarlo si tienes GNU ; de lo contrario, deberá canalizar la lista de archivos .-exec command {} +findxargs command

(In this answer I'm not going to bother with the usual -print0 suggestion, because if you don't have GNU find, you won't have -print0 or even GNU xargs either. However, if your version of xargs does support -d '\n', use that, because the default way xargs parses input isn't very safe.)

Note that this might still result in multiple wc invocations, because most operating systems (except maybe Hurd) have a limit on the maximum command-line length and/or maximum number of arguments to a single command, which a large number of files might exceed. @slhck's suggestion of using **/*.py would also hit the same limit (early Unixes having had very low limits is why xargs was created in the first place).

Another alternative is to use awk for the final calculation:

find ... | awk '$2 != "total" {sum += $1; print}
                END {printf "%7d total\n", sum}'
grawity
fuente
Out of curiosity, have you hit the limit in practice already? (Of course I think it should be mentioned regardless.)
slhck
@slhck: Once – when trying to remove everything from pacman's downloaded package cache. (I had mistakenly used an absolute path in the command, so that doubled the length of every path.) I've gotten used to find -delete as an alternative to rm -rf * since then.
grawity