Estou tentando adicionar um cabeçalho de licença a todos os arquivos de cabeçalho e arquivos de origem em um diretório de projeto usando um loop for. Isso não está funcionando, existe alguma outra abordagem usando sed
?
Estou tentando adicionar um cabeçalho de licença a todos os arquivos de cabeçalho e arquivos de origem em um diretório de projeto usando um loop for. Isso não está funcionando, existe alguma outra abordagem usando sed
?
Respostas:
for f in **/*.cpp; do
cat header_file $f > $f.new
mv $f.new $f
done
globstar
bash para que isso funcione.
Este é mais ou menos apenas um comentário estendido sobre a resposta de Daniel Serodio . Comecei a escrever como um comentário, mas rapidamente cresceu muito ...
Para que um bash glob seja recursivo, é necessário shopt -s globstar
. Você deve ativar o globstar, caso contrário **
não funcionará. A opção de shell globstar foi introduzida na versão 4 do bash.
Para evitar o processamento de um diretório como my.cpp/
, use o teste [[ -f $f ]]
... Quando o teste está entre colchetes duplos, as variáveis não precisam ser citadas duas vezes.
Você também pode considerar a possibilidade de não haver arquivos correspondentes usando shopt -s nullglob
, o que permite que os padrões que não correspondem a arquivos sejam expandidos para uma cadeia nula, e não para eles próprios.
Para lidar com múltiplos padrões, você pode encadear os padrões glob: **/*.cpp **/*.h
, mas talvez de preferência, quando a opção shell extglob é na via shopt -s extglob
, você pode usar tais construções, como **/*.@(cpp|h)
o que evita várias passagens sobre o sistema de arquivos; uma vez para cada padrão.
Se você deseja .files
ser incluído, use .*.cpp
etc ou useshopt -s dotglob
Para manipular com segurança a modificação de um arquivo que está sendo canalizado, use sponge
from package moreutils
(economiza a necessidade de criar seu próprio arquivo temporário)
printf "// The License\n\n" > /tmp/$USER-license
shopt -s globstar nullglob extglob
for f in **/*.@(cpp|h) ;do
[[ -f $f ]] && cat "/tmp/$USER-license" "$f" | sponge "$f"
done
[[
pode lidar normalmente com um nulo $f
.
unset x; [ -f $x ] && echo exists
relatórios "existe" ... (fixo)
**/*.@(cpp|h)
por$( find . -name "*.h" -name "*.cpp")
Obrigado @fred, @maxmackie, @enzotib.
Você pode, por favor, verificar o procedimento que segui.
#!/bin/sh
# script to copy the headers to all the source files and header files
for f in *.cpp; do
if (grep Copyright $f);then
echo "No need to copy the License Header to $f"
else
cat license.txt $f > $f.new
mv $f.new $f
echo "License Header copied to $f"
fi
done
caso contrário, o cabeçalho da licença será copiado para vários números de vezes.
Por favor, sugira-me um padrão para percorrer todos os cabeçalhos e fontes no diretório e subdiretórios do projeto.
Não consegui entender completamente o que o @fred sugeriu.
targln=2; findln=$(sed -rne $targln'{\|// Copyright|=;q}' "$f"); if ((findln==targln));then
... mas, é claro, acima e além de tudo o mais, teste-o primeiro ... PS. É par para o curso aqui no Unix e Linux para postar esses extras na sua pergunta original, não como uma resposta ...
grep
, adicione a -q
opção a grep
. Sempre adicione aspas duplas $f
.
Você pode fazer isso com ex
ou ed
se preferir (não o faça sed
conforme solicitado), sed
foi projetado para editar fluxos, -i
é uma má ideia por vários motivos):
shopt -s globstar
for _file in **/*.@(cpp|h); do
ed -s "${_file}" << EOF
0a
/* This file is licensed under the foo license.
All copyright strictly enforced by the copyright monster. */
.
w
EOF
done
sed -i
uma má ideia?
sed -i
quebra links simbólicos e hardlinks, resultando em comportamento inesperado. Na melhor das hipóteses, não é intuitivo; na pior, é ativamente prejudicial.
#!/bin/bash
for i in `find . -name '*.[m|h]'` # or whatever other pattern...
do
echo $i
if ! grep -q Copyright $i
then
cat copyright.txt $i >$i.new && mv $i.new $i
fi
done
enter code here
A postagem do blog anexou um tar.gz
arquivo, contendo os arquivos necessários.
Ele tem um header.template
arquivo, onde você pode escrever um comentário personalizado, pode abranger várias linhas.
Ele possui um remove_header.awk
script que substitui os cabeçalhos existentes pelo novo cabeçalho.
Para executá-lo:
find . -name "*.h" -exec ~/rh/replace_header.sh {} \;