J'essaie d'ajouter un en-tête de licence à tous les fichiers d'en-tête et fichiers source dans un répertoire de projet à l'aide d'une boucle for. Cela ne fonctionne pas, existe-t-il une autre approche sed
?
J'essaie d'ajouter un en-tête de licence à tous les fichiers d'en-tête et fichiers source dans un répertoire de projet à l'aide d'une boucle for. Cela ne fonctionne pas, existe-t-il une autre approche sed
?
Réponses:
for f in **/*.cpp; do
cat header_file $f > $f.new
mv $f.new $f
done
globstar
en bash pour que cela fonctionne.
Il s'agit plus ou moins d'un long commentaire sur la réponse de Daniel Serodio . J'ai commencé à l'écrire comme un commentaire, mais il est rapidement devenu trop grand ...
Pour qu'un glob bash soit récursif, il faut shopt -s globstar
. Vous devez activer globstar, sinon **
cela ne fonctionne pas. L'option shell globstar a été introduite dans la version 4 de bash.
Pour éviter de traiter un répertoire tel que my.cpp/
, utilisez le test [[ -f $f ]]
... Lorsque le test est entre crochets doubles, les variables n'ont pas besoin d'être mises entre guillemets.
Vous pouvez également envisager la possibilité qu'il n'y ait aucun fichier correspondant en utilisant shopt -s nullglob
, ce qui permet aux modèles qui ne correspondent à aucun fichier de se développer en une chaîne nulle, plutôt qu'eux-mêmes.
Pour gérer plusieurs modèles, vous pouvez enchaîner les modèles glob: **/*.cpp **/*.h
, mais peut - être de préférence, lorsque l'option shell extglob est sur via shopt -s extglob
, vous pouvez utiliser ces constructions telles que ce **/*.@(cpp|h)
qui évite plusieurs passages sur le système de fichiers; une fois pour chaque motif.
Si vous voulez .files
être inclus, utilisez .*.cpp
etc, ou utilisezshopt -s dotglob
Pour gérer en toute sécurité la modification d'un fichier en cours de piping, utilisez sponge
from package moreutils
(cela vous évite de créer votre propre fichier temporaire)
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
[[
peut gracieusement gérer un null $f
.
unset x; [ -f $x ] && echo exists
**/*.@(cpp|h)
par$( find . -name "*.h" -name "*.cpp")
Merci @fred, @maxmackie, @enzotib.
Pouvez-vous s'il vous plaît vérifier la procédure que j'ai suivie.
#!/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
sinon l'en-tête de licence sera copié plusieurs fois.
Veuillez me suggérer un modèle pour parcourir tous les en-têtes et sources du répertoire et des sous-répertoires du projet.
Je n'ai pas pu comprendre pleinement ce que @fred a suggéré.
targln=2; findln=$(sed -rne $targln'{\|// Copyright|=;q}' "$f"); if ((findln==targln));then
... mais, bien sûr, au-delà de tout le reste, testez-le soigneusement en premier ... PS. C'est normal pour le cours ici à Unix et Linux de publier de tels extras dans votre question d'origine, pas comme réponse ...
grep
, ajoutez l' -q
option à grep
. Ajoutez toujours des guillemets $f
.
Vous pouvez le faire avec ex
ou ed
si vous préférez (vous ne devriez pas le faire avec sed
comme vous l'avez demandé, sed
est conçu pour modifier les flux, -i
est une mauvaise idée pour diverses raisons):
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
une mauvaise idée?
sed -i
rompt les liens symboliques et les liens physiques, ce qui entraîne un comportement inattendu. Au mieux, il n'est pas intuitif, au pire, il est activement nocif.
#!/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
Le billet de blog a joint un tar.gz
fichier contenant les fichiers nécessaires.
Il a un header.template
fichier, où vous pouvez écrire un commentaire personnalisé, il peut s'étendre sur plusieurs lignes.
Il a un remove_header.awk
script qui remplace les en-têtes existants par le nouvel en-tête.
Pour l'exécuter:
find . -name "*.h" -exec ~/rh/replace_header.sh {} \;