grep para exibir pastas que contenham arquivos que contenham uma string

5

Eu preciso executar um grep no meu servidor para procurar por arquivos que estendam um arquivo do CodeIgniter 1, pois estamos atualizando para o CI2. Em uma pasta contém várias centenas de pastas específicas do site, como:

dev/sitea.com/site/www
dev/siteb.com/site/www
dev/sitec.com/site/www
... and so on

Como posso grep para encontrar quais pastas diretamente sob dev contêm um arquivo (ou muitos arquivos em subpastas variáveis) que referenciam a string "MY_Output" (arquivo php)

Estou ciente do sinal -l para listar os arquivos, mas não sei como colocá-lo com outros sinalizadores juntos para dizer " mostra quais sites contêm arquivos com essa string "

Isso é possível? Obrigado!

EDIT: Apenas para esclarecer, essas pastas no nível do site conterão arquivos que estendem MY_Output.php, que é um arquivo compartilhado comum:

class Whatever extends MY_Output
    
por AlienWebguy 14.07.2011 / 20:17

9 respostas

17

Essa seria minha abordagem:

find dev -type f -print0 | \          # find all files
xargs -0 grep 'extends MY_Output' | \ # search for your string
cut -d/ -f2  | \                      # extract web folder name
sort | uniq                           # eliminate duplicates

Observe o uso do parâmetro print0 para find e o sinal -0 (zero) para xargs , o que evita problemas se os nomes dos arquivos tiverem espaços incorporados neles.

    
por 18.07.2011 / 08:36
4

Eu vejo muita complexidade desnecessária nas várias soluções postadas. Considere o seguinte:

grep -r [regex to find] [path to search] | awk -F: '{print $1}' | uniq
    
por 21.07.2011 / 19:09
3

Para descobrir quais sites têm um arquivo com MY_output.php dentro deles, siga estas etapas:

Faça login no servidor usando o PuTTY. Você deve receber um prompt de comando assim:

username@hostname:~$

Mude para o seu diretório dev (não tenho certeza onde isso está no seu servidor, talvez sob / var / www?)

cd /var/www/dev

Verifique se estamos no diretório correto

ls

E devemos conseguir algo assim:

sitea.com
siteb.com
sitec.com

Agora, encontre todos os arquivos que contenham MY_output.php e encurte a lista apenas para os domínios:

grep -rsl "extends MY_output" * | cut -d/ -f1 | sort | uniq

O Grep procura todos os arquivos correspondentes recursivamente em todos os diretórios da web. O comando cut divide seus caminhos e apenas fornece o primeiro nome de diretório (sitea.com, siteb.com, etc.) Os comandos sort e uniq apenas removem entradas duplicadas para que cada domínio apareça apenas uma vez.

Aproveite!

    
por 15.07.2011 / 16:03
1

use find para listar todos os arquivos e, em seguida, execute grep em cada um deles:

find dev/ | xargs grep -l MY_Output.php 

Nota : você deve estar no diretório que contém o diretório dev

e se você receber erros de arquivos ilegíveis (permissões etc), então você pode acrescentar 2>/dev/null

find dev/ | xargs grep -l MY_Output.php 2>/dev/null
    
por 14.07.2011 / 20:28
1

Você pode fazer isso com grep , mas acho que a lógica necessária justifica o uso de um script ... Este é um script python rápido que pesquisará com base nos parâmetros fornecidos acima ...

Primeiro, ele procura, de forma recursiva, de ROOT_DIRECTORY para qualquer arquivo que corresponda a FILE_FILTER ... e então procura cada um desses arquivos por uma string correspondente a SEARCH_STRING . Se encontrar qualquer arquivo correspondente ao SEARCH_STRING , ele registrará a correspondência e imediatamente ignorará os arquivos restantes nesse diretório, passando para o próximo arquivo em all_files que ainda não teve uma correspondência (economizando um pouco de CPU e desgaste do disco).

Se eu tiver feito suposições incorretas, você poderá editar as variáveis chamadas FILE_FILTER , SEARCH_STRING e ROOT_PATH .

Salve o script abaixo como searchme.py e execute-o com python searchme.py

===

import os
import re
import sys

def get_directory(path):
    return '/'.join(path.split('/')[0:-1])

FILE_FILTER = '(\.htm|\.php)'
SEARCH_STRING = 'MY_Output'
ROOT_PATH = '~/'

all_files = []
retval = {}
rootdir = os.path.expanduser(ROOT_PATH)

## Find all files matching FILE_FILTER
for root, subFolders, files in os.walk(rootdir):
    for file in files:
        pname = os.path.join(root,file)
        if re.search(FILE_FILTER, pname) is not None: all_files.append(pname)
        retval[get_directory(pname)] = False

## Search files for SEARCH_STRING; take shortcut if string is found
for pname in all_files:
    path = get_directory(pname)
    if not retval[path]:
        try:
            for line in open(pname):
                if SEARCH_STRING in line:
                    retval[path] = True; break
        except IOError:
            ## Occasionally firefox makes lock files that can't be opened...
            ##     Ignore any permission errors...
            pass

## Print resultant directories...
for path in sorted(retval.keys()):
    if retval[path]: print path
    
por 17.07.2011 / 04:13
0

Se você entrar no seu servidor e, em seguida, cd para a pasta dev, isso deve funcionar:

egrep -rl 'class \S+ extends MY_Output' * | awk -v FS="/" '{print $2}' | sort | uniq -c

Isso selecionará APENAS sites que realmente possuem classes que estendem a classe MY_Output, além de fornecer uma contagem de arquivos dentro desse site que você pode esperar alterar. Você também pode usar o utilitário de corte em vez de awk:

egrep -rl 'class \S+ extends MY_Output' * | cut -d/ -f2 | sort | uniq -c
    
por 17.07.2011 / 13:45
0

Pelo que entendi, em termos gerais você deseja listar quais pastas contêm arquivos regulares chamados dev / * / * que contêm a cadeia " MY_Output " (case sensível).

Mais precisamente, como o padrão "*" não corresponde a arquivos ou diretórios que começam com ".", você também deve procurar por dev / * / * , dev / . * / * , dev /*/.??* e dev /.??*/.??*. Esse é um detalhe que está faltando nas soluções da secretmike e Brian Showalter.

O uso desses quatro padrões garante que você processe todos os arquivos desejados e que não obtenha correspondências extras de outros arquivos (mais profundos ou mais rasos). Normalmente, a lista de arquivos correspondentes pode ser executada simplesmente executando:

grep -l MY_Output dev/*/* dev/.??*/* dev/*/.??* dev/.??*/.??* 2>/dev/null 

A parte 2 > / dev / null existe para ignorar erros como quando você tenta ler arquivos sem permissões, como você parece estar fazendo (com base na sua resposta à resposta de Imre L) . Para melhores resultados, você pode querer executar este comando como root.

Infelizmente, há um limite para comprimentos de linha de comando, e este comando pode falhar se houver muitos arquivos correspondentes, porque a linha de comando seria muito longa (após a expansão). Como você diz que há centenas de diretórios em dev , essa abordagem não é apropriada, embora eu ache que vale a pena mencionar aqui por completo.

Para evitar esse problema, o comando find é mais adequado:

find dev -mindepth 2 -maxdepth 2 -type f \
    -exec bash -c 'grep -q MY_Output {} && echo {}' \;

Isso é muito semelhante à resposta que Imre L deu, embora ele recorra a xargs em vez de usar a opção -exec . Mas isso só lhe dá a lista de arquivos correspondentes, não a lista de pastas que os contém.

Para conseguir o que você deseja, precisamos filtrá-lo um pouco mais:

find dev -mindepth 2 -maxdepth 2 -type f \
    -exec bash -c 'grep -q MY_Output {} && dirname {}' \; \
        | sort \
        | uniq

Os switches -mindepth e -maxdepth garantem que não recebamos correspondências de arquivos mais profundos ou mais rasos na árvore dev .

    
por 18.07.2011 / 06:35
0

Acho que faria algo assim:

for dir in dev/* ; do
    if [ -d "$dir" ] ; then
        if [ -n "$( find "$dir" -type f \
            -exec grep -q '\<MY_Output\>' {} \; \
            -print | head -1 )" ] ; then
            echo "$dir"
        fi
    fi
done

Ou como um verso:

for dir in dev/* ; do [ -d "$dir" ] && [ -n "$( find "$dir" -type f -exec grep -q '\<MY_Output\>' {} \; -print | head -1 )" ] && echo "$dir" ; done
    
por 18.07.2011 / 20:04
0
find (Directory) -iname "(File Pattern>)" -exec zgrep "(String to Find)" {} \;

Por exemplo:

find /opt/WebSphere/AppServer/profiles/application/logs/ -iname "SystemOut*" -mtime -7 -exec zgrep "FileNotFoundException" {} \;
    
por 23.12.2013 / 21:42

Tags