Recherche de script Bash pour un fichier et remplacement si chaîne trouvée à l’intérieur du fichier à l’aide de caractères génériques

Je travaille sur un script bash qui recherchera un fichier spécifique en utilisant le chemin générique pour rechercher, une fois qu’il trouve ce nom de fichier qu’il recherche dans le fichier pour un terme spécifique et le remplace ensuite.

Voici ce que j’ai déjà mis en place:

#!/bin/sh PATH=${1} FILENAME="$2" SEARCHFOR="$3" /usr/bin/clear echo "Searching $PATH" echo "For the file $FILENAME" echo "With the ssortingng $SEARCHFOR" echo "==========================" echo " RESULTS " echo "==========================" /usr/bin/find $PATH -type f -name "$FILENAME" | /usr/bin/xargs /bin/grep -l "$SEARCHFOR" 

Je n’ai pas encore ajouté le remplacement mais j’ai pensé que j’utiliserais SED au lieu de grep pour le faire, en utilisant simplement grep à des fins de test.

Avec le code ci-dessus, je dois utiliser des guillemets pour tout type de chemin d’access générique. Y a-t-il un moyen de contourner ceci?

 ./script '/home/*/public_html' php.ini module.so 

Je pensais peut-être utiliser des arguments, mais il doit y avoir une autre façon de le faire.

Mon but ultime est d’avoir un script bash auquel je peux transmettre un chemin d’access ou un nom de fichier, il recherchera ce fichier, une fois qu’il trouvera le fichier qu’il recherchera pour un terme spécifique et le remplacera s’il est trouvé.

Ça a l’air si simple et ça devrait être le cas mais je me tape la tête contre le bureau parce que ça fait tellement longtemps que je n’ai pas réussi à me défoncer avec bash … aaggghh aide!

Tout d’abord, c’est une mauvaise idée d’avoir des noms de variables en majuscules, en particulier PATH puisque vous seriez en train de réinitialiser la variable d’environnement PATH (faites simplement un echo $PATH dans l’invite et comprendre ce que je veux dire, et c’est probablement l’une des raisons pour lesquelles vous avez dû utiliser /usr/bin/clear au lieu de clear puisque la variable env PATH est modifiée). Donc, il est toujours recommandé d’utiliser des variables avec des minuscules comme path .


Le problème auquel vous êtes confronté concerne l’expansion glob de * dans le sous-shell. Lorsque vous utilisez

 ./script '/home/*/public_html' php.ini module.so 

le * n’est pas développé à l’invite (shell parent) mais est développé dans le sous-shell du script. Mais quand vous utilisez

 ./script /home/*/public_html php.ini module.so 

le * est développé dans le shell parent (ce qui se traduirait par un chemin aléatoire comme indiqué par le shell) et est ensuite transmis dans le sous-shell du programme –

Alors, /home a des répertoires /user , /apps , /data making $ cd * vous amènera au répertoire qui est alphabétiquement en premier, à savoir /apps . Donc /home/* sans les guillemets dans le shell parent pointera toujours vers /home/apps ce qui n’est pas ce que nous voulons!

Un remède immédiat à cela est comme ci-dessous

 $set -o noglob #unset glob expansion $./script /home/*/public_html php.ini module.so #your command without quotes & wildcard */ $set +o noglob #re-set glob expansion back 

ou

 $set -o noglob;./script /home/*/public_html php.ini module.so;set +o noglob 

Essayez $echo * puis $set -o noglob;echo *;set +o noglob pour un exemple rapide.

Avertissement – Si vous échouez ou oubliez de remettre noglob ( set +o noglob ), le shell traitera les caractères comme * et ? comme des personnages normaux et ne les élargira pas, ce qui pourrait entraîner des résultats indésirables et de la confusion.

 find $path -name \*$filenamepattern\* -exec sed -i.bak 's/find/replace/g' {} ';' 
  • sed -i va trouver et remplacer à l’intérieur du fichier et sauvegarder dans le fichier
  • supprimer la partie .bak si vous ne souhaitez pas sauvegarder les fichiers
  • option levier -exec de trouver pour éviter un peu plus lourd xargs

Réorganisez simplement vos arguments et mettez la liste des répertoires à rechercher à la fin. Alors:

 #!/bin/sh FILENAME="${1?No filename specified}" SEARCHFOR="${2?No target ssortingng given}" shift; shift; SEARCHPATH="$@" 

Vous devriez alors être en mesure de laisser le rest inchangé (autre que de changer le nom PATH en SEARCHPATH, car changer le PATH est une très mauvaise idée) et l’appeler comme:

 $ ./script php.ini module.so /home/*/public_html 
 find `filepath` -name `filename`|xargs sed 's/find/replace/' 

pour moi, j’utiliserais find et sed pour terminer le travail.

Cela résoudra le problème du passage de caractères génériques à un script bash, mais veuillez respecter le premier point.

 #!/bin/bash -f directory=$1 filename=$2 searchfor=$3 replacement=$4 sedpattern=s/$searchfor/$replacement/g find $directory -name $filename -exec sed -i.bak $sedpattern {} ';' 
  • IMPORTANT lorsque vous invoquez ce script sur la ligne de commande, vous devez échapper votre barre oblique inverse;
    • % ./thisscript . \*.csv oldword newword
  • l’option bash -f désactive la mise en mémoire au bon moment – lorsque le sous-shell bash est invoqué pour la première fois, ce qui signifie avant que les parameters ne soient analysés;
  • trouver commande execs sed sur tous les fichiers qui correspondent
  • Le moyen le plus simple de passer un motif de recherche-remplacement à sed qui contient d’autres variables définies dans un script est de placer le motif lui-même en premier dans une variable
  • L’option -i.bak crée un nouveau fichier avec les remplacements, ainsi que la sauvegarde du fichier d’origine