Remover cadeia longa de arquivos

4

Os arquivos no meu servidor foram corrompidos. Eu quero remover uma seqüência de caracteres 13000 de todos os arquivos PHP que o contenham.

A string parece:

?php if(!isset($GLOBALS["\x616\x756\x61"])) { $ua=strtolower($_SERVER[ ... $qhroczocgv=$qjhvvbyvyv; $qhroczocgv=(729-608); $boxknervrr=$qhroczocgv-1; ?>

Com elipses inseridas por brevidade.

Quando pesquiso a string usando grep , recebo uma

grep: Invalid back reference" despite escaping \![]$

Como eu primeiro encontro todos os arquivos com a string inteira e, em seguida, como removo o texto de todos os arquivos?

    
por user138341 13.10.2015 / 22:20

3 respostas

5

Supondo que você tenha convenções decentes de codificação, basta excluir qualquer linha maior que um determinado tamanho:

shopt -s extglob nullglob
sed -i.bak -r '/.{10000}/d' **/*.php

para @wildcard:

find . -name '*.php' -print0 | while IFS= read -rd "" file; do
    before=$(wc -l < "$file")
    after=$(sed -r '/.{10000}/d' "$file" | wc -l)
    case $(( diff = before - after )) in
        0) :;;  # no-op
        *) echo "will remove $diff lines from $file";;
    esac
done
    
por 13.10.2015 / 22:47
2

Experimente com fgrep ou, equivalentemente, grep -F . Isso interpretará o padrão como uma string fixa.

Você também pode colocar essa única string em um arquivo (por si só) e usar grep -f filename para especificar o arquivo. Você ainda precisará da bandeira -F .

Veja man grep para outras opções; existem vários que podem ser úteis.

Para várias formas de excluir uma linha que corresponde a um determinado padrão, consulte o link .

Juntando tudo, uma abordagem é:

  1. Coloque essa linha de texto em um arquivo por si só. Chame de "patternfile".
  2. Executar grep -lrFf patternfile . > filelist
  3. Edite o filelist para remover a linha ./patternfile
  4. Executar for i in $(cat filelist) ; do grep -vf patternfile $i > temp && chmod --reference=$i temp && mv temp $i ; done

Na etapa 2, as opções do grep são: -l para listar os arquivos correspondentes; -r para recursar em subdiretórios; -F para usar uma string fixa como um padrão para corresponder; -f para usar o arquivo patternfile como o padrão a ser correspondido; então, é claro, > filelist para criar um arquivo contendo a lista de arquivos correspondentes.

Na etapa 4, grep simplesmente usa o sinal -v para imprimir não linhas de correspondência e, em seguida, chmod garante que você não terá problemas de permissões e mv coloca o arquivo de volta no lugar.

Pode haver maneiras melhores, mas acho que isso será suficiente.

EDIT: Se você estiver executando isso como root , e nem todos esses arquivos pertencerem a root, faça a seguinte versão revisada da etapa 4:

for i in $(cat filelist) ; do grep -vf patternfile $i > temp && chown --reference=$i temp && chmod --reference=$i temp && mv temp $i ; done

O passo 4 original é bom se você for o proprietário de todos os arquivos.

    
por 13.10.2015 / 22:25
0

Supondo que essa string seja bastante exclusiva em seus arquivos, você pode usar um regex para encontrar algumas partes notáveis da string e um find com um sed replace para desativá-la

 find . -name "*.php" -exec sed -i 's/?php.*strtolower.*qhroczocgv.*boxknervrr.*-1; ?>//g' {} \;

Isso deixará uma linha em branco em seu lugar.

Você sabe se esta string será a única coisa na linha em que está presente? se assim você poderia tentar dar um jeito:

find . -name "*.php" -exec sed -i 's/?php.*strtolower.*qhroczocgv.*boxknervrr.*-1; ?>//g' {} \;

O qual irá procurar por uma string que tenha php, qualquer número de outros caracteres seguido por strtolower qualquer número de outros caracteres seguido por qhroczocgv seguido por qualquer número de outros caracteres seguido por boxknervrr seguido por qualquer número de outros caracteres e exclua a linha inteira.

Também na porção find , . representa, é claro, o diretório atual, mas você pode mudar isso para o diretório de sua escolha.

    
por 13.10.2015 / 22:38