Bash: ¿hay alguna manera de buscar una cadena particular en un directorio de archivos? [duplicar]

47

Posible duplicado: busque
un patrón de texto en Linux

En bash, me preguntaba si había algún comando que le permitiera saber si una cadena particular que está buscando existe dentro de los archivos ubicados en el directorio actual en el que se encuentra.

Supongamos que está buscando la función 'toUpperCase ()' dentro de un conjunto de archivos C en su directorio actual. Hay muchos archivos, por lo que no querrá abrir cada uno manualmente usando vim y verificar la cadena 'toUpperCase' porque eso tomaría mucho tiempo. Si no es una línea de comando bash, ¿hay otro método para hacerlo de manera eficiente?

Templario oscuro
fuente

Respuestas:

64

Con grep:

grep -R "toUppercase()" *

O, si tiene instalado ack-grep , simplemente:

ack-grep "toUppercase"

Si desea limitar la búsqueda en archivos C, con ack-grep:

ack-grep -cc "toUppercase()"

ack-greptambién se puede instalar en OSX pero el ejecutable se llama solo ack.

Trasplazio Garzuglio
fuente
Tanto es así que SO ya tiene una pregunta sospechosamente similar ;)
David Perry
10

La herramienta de búsqueda de texto estándar es grep .

Para buscar la cadena toUpperCase(en todos los .carchivos en el directorio actual:

grep -F 'toUpperCase(' *.c

Si desea buscar también en subdirectorios:

grep -r --include='*.c' -F 'toUpperCase('

Si está buscando llamadas a funciones C, entonces ctags puede ser mejor. Lo ejecuta una vez en todos sus archivos de origen para crear un índice de identificadores, luego usa su editor para navegar entre las llamadas. Todos los editores similares a vi pueden usar el TAGSarchivo de ctags . Si usa Emacs, ejecute el programa similar etags.

Gilles 'SO- deja de ser malvado'
fuente
ctagses útil para encontrar definiciones de funciones , no llamadas de funciones .
JdeBP
6

Estás usando vim. Tienes una herramienta para hacer esto incorporada.

Como era de esperar, hay siete respuestas que ya dicen usar grep. Pero parece ser la única persona hasta ahora que se ha dado cuenta de su pregunta que está utilizando vim. Como tal, aunque se puede utilizar grepdesde dentro vim, se puede también utilizar vim's herramienta integrada. Esto se invoca a través del :vimgrepcomando.

Para buscar "todos los archivos fuente de C en el directorio actual para llamadas a la función toUpperCase()" uno escribe el vimcomando

:vimgrep "\<toUpperCase\_s*(" *.c

La lista de coincidencias resultante se carga automáticamente en la lista de soluciones rápidas, a la que se puede acceder con cualquiera de los dos (consulte la ayuda en línea para ver la sutil diferencia)

:copen
:cwin

Para encontrar la definición de la función , en lugar de las llamadas, ctagses la herramienta, como se menciona en Gillesla respuesta de , junto con los comandos :tjumpo :tselect.

¿Por qué usar :vimgrep?

La ayuda en línea ( :help grep) enumera varias de las razones, que no mencionaré aquí. Además de eso, compare la acción de :vimgrepcon dietbuddhala respuesta de . dietbuddhaLa línea de comando de la horquilla bifurca un grepproceso individual para cada archivo fuente C individual. Ni siquiera se emplea xargspara reducir esa sobrecarga. Y aún tiene que analizar de alguna manera el resultado para invocar su editor de texto en los archivos fuente relevantes una vez que haya terminado. :vimgrepno bifurca múltiples procesos adicionales en absoluto, y usar el resultado es la simplicidad misma. Simplemente seleccionando una de las entradas en la lista de soluciones rápidas resultante, se posiciona automáticamente el cursor en la línea relevante del archivo fuente relevante.

De hecho, hace exactamente lo que escribiste que harías a mano, excepto automáticamente. Es la forma automatizada de hacer esas mismas acciones del editor de texto. Carga el archivo como si se cargara a mano, busca una expresión regular (usando la misma sintaxis de expresión regular que ya está usando en otra parte vim), registra los lugares donde ocurren las coincidencias y luego descarga el archivo.

JdeBP
fuente
2

Sí, se llama la herramienta grep.

El comando grep busca en uno o más archivos de entrada líneas que contengan una coincidencia con un patrón especificado. Por defecto, grep imprime las líneas coincidentes.

El uso básico es:

grep something somewhere

O, más específicamente:

grep [some options] pattern file

En un caso muy simple, desea buscar de forma recursiva en todos los archivos, por lo que proporciona la -ropción. Si no le importan las mayúsculas o minúsculas, no distinga entre mayúsculas y minúsculas con la -iopción.

grep -ri "touppercase()" .

Si solo desea las partes coincidentes, use la -oopción.

Grep puede usar expresiones regulares , y tiene un gran manual .

slhck
fuente
2

grepes la respuesta estándar: usar el indicador -r para buscar de forma recursiva o en conjunto con find(discusión y ejemplos en otras preguntas en este sitio, como este )

Mi elección preferida últimamente es ack. Probablemente no esté instalado en su computadora, pero puede instalarlo usando apt-get en Ubuntu o simplemente descargarlo. Los enlaces, instrucciones y razones por las que es mejor que grep están disponibles en http://betterthangrep.com/

Doug Harris
fuente
1

find y grep

find myproject -name '*.c' -exec grep 'toUpperCase(' {} \; -print

¿Por qué no solo grep?

grep -r string .se repetirá a través de todos los archivos en el directorio actual. Si tiene archivos de objetos u otros archivos binarios, puede obtener una coincidencia con resultados binarios aka. basura. Si también tiene archivos de dispositivo o de Fifos en su subdirectorio, puede tener consecuencias desconocidas / no deseadas.

grep string *.csolo busca los .carchivos de directorios actuales .

grep string **/*.c busca en todos los subdirectorios. Sin embargo, si tiene una gran cantidad de .carchivos, corre el riesgo de exceder la cantidad máxima de expansiones para el shell glob. La expansión también tiene que suceder primero, lo que significa un recorrido completo del árbol antes de que grepcomience.

dietbuddha
fuente
0

Grep hará el truco, pero un poco de secuencia de comandos adicional ayudará a encontrar el nombre del archivo y la línea exacta referenciada. Si eso es lo que quieres, creo que lo siguiente funciona bien. Lo tengo guardado como un script de shell y le paso el valor que quiero como primera opción de línea de comando.

for i in $(ls)
do
    cat $i 2> /dev/null | grep $1 > /dev/null 2>&1
    STATUS=$?
    if [ $STATUS  -eq 0 ] ; then
        echo $i
        cat $i | grep -n $1
    fi
done
Tim Brigham
fuente
3
grep tiene una opción -H que ya hace esto. grep -Hn lo que sea *
Roy Rico
Aprenda algo nuevo todos los días .. Gracias @ Roy Rico
Tim Brigham
0

Me parece interesante que nadie haya respondido a su pregunta específica: "¿cómo puedo encontrar si existe una cadena en particular dentro de los archivos ubicados en el directorio actual". Hasta donde sé, no hay una opción grep que solo devuelva si se ha encontrado una coincidencia en un grupo de archivos. La opción más cercana es -l para enumerar los nombres de archivo. La respuesta más cercana entre las que hasta ahora es de tim, con algunos pequeños ajustes:

#!/usr/bin/bash

for i in $(ls *.c 2> /dev/null)
do
    cat $i 2> /dev/null | grep $1 > /dev/null 2>&1
    STATUS=$?

    if [ $STATUS  -eq 0 ] ; then
        echo "Found"
        exit
    fi
done

echo "Not found"

Puede hacer que este script de shell sea más genérico aceptando un segundo argumento para la extensión del archivo sin demasiados problemas.

Doug

SnoopDougieDoug
fuente