Como obter nomes de arquivos ao usar localizar e sed

3

Estou escrevendo um script para aplicar sed em determinados arquivos e, em seguida, listar arquivos que foram alterados para que eu saiba quais foram modificados.

É assim que eu estou encontrando e usando o sed:

find . -type f -a \( -name "*.txt" -o -name "*.git"\) -a -exec sed -i -e "s/"str1"/"str2"/g" {} +

Como imprimo o nome do arquivo dos arquivos alterados? Gostaria de imprimi-lo em uma ordem classificada para facilitar a leitura.

Ao usar apenas sed, podemos fazer isso:

sed -i 's/$pattern/$new_pattern/w changelog.txt' $filename
if [ -s changelog.txt ]; then
  # CHANGES MADE, DO SOME STUFF HERE
else
  # NO CHANGES MADE, DO SOME OTHER STUFF HERE
fi

Mas como faço isso quando uso encontrar e sed juntos? Eu verifiquei a página do manual e tentei um monte de coisas, mas nada funcionou.

    
por KLMM 21.01.2016 / 15:31

3 respostas

0

Deve ser fácil escrever um pequeno script que faça o que você deseja e exec do script como um argumento para find . Você já tem o script e, se substituir $filename por $1 , você o terá. Seu script será da forma

#!/bin/bash
sed -i 's/$pattern/$new_pattern/' $1
echo $1 >> changelog

Vamos chamar esse script ed_notify . Agora, você pode executá-lo em arquivos selecionados por

cat changelog >> changelog.old
rm changelog
find . -type f -a \( -name "*.txt" -o -name "*.git"\) -a -exec ed_notify {} \;
    
por 21.01.2016 / 15:51
0

Seu comando sed (com cotação apropriada):

sed 's/str1/str2/g'

Isso alterará todas as ocorrências de str1 em str2 . Uma lista de arquivos contendo str1 pode ser obtida de grep -l 'str1' :

find . -type f \( -name '*.txt' -o -name '*.git \) \
    -exec grep -l 'str1' {} \; \
    -exec sed -i 's/str1/str2/g' {} + >changelist.txt

Aqui, grep -l fornecerá uma lista de nomes de caminho que serão redirecionados para changelist.txt . Ele também atuará como um filtro para sed , de modo que sed seja executado apenas em arquivos que contenham o padrão. sed -i fará as alterações nos arquivos (e permanecerá silencioso).

Como alternativa, deixe find imprimir os nomes de caminho dos arquivos que contêm a string:

find . -type f \( -name '*.txt' -o -name '*.git \) \
    -exec grep -q 'str1' {} \; \
    -print \
    -exec sed -i 's/str1/str2/g' {} + >changelist.txt

Relacionados:

por 23.09.2017 / 16:39
0

sed -i reescreve o arquivo (na verdade, faz cópias novas dos arquivos) independentemente de qualquer um dos comandos s no script sed ter sido bem-sucedido ou não.

Aqui, você deseja evitar a execução de sed -i nos arquivos que não contêm str1 . Com ferramentas GNU:

find . -type f \( -name "*.txt" -o -name "*.git" \) -size +3c \
  -exec grep -lZ str1 {} + |
  while IFS= read -rd '' file; do
    sed -i 's/str1/str2/g' "$file" &&
      printf '%s\n' "$file"
  done

Isso executa um sed para cada um dos arquivos que contêm str1 e imprime os nomes dos arquivos se sed tiver sido bem-sucedido (para o qual não houve erro na criação da nova versão do arquivo).

Ou você pode executar um grep e sed por arquivo:

find . -type f \( -name "*.txt" -o -name "*.git" \) \( -size +3c \
  -exec grep -q str1 {} \; \
  -exec sed -i 's/str1/str2/g' {} \; \
  -printf '"%p" was modified\n' \
    -o -printf '"%p" was not modified\n"' \)
    
por 05.09.2018 / 14:11