J'ai un fichier qui contient les noms des répertoires :
my_list.txt
:
/tmp
/var/tmp
J'aimerais vérifier dans Bash avant d'ajouter un nom de répertoire si ce nom existe déjà dans le fichier.
J'ai un fichier qui contient les noms des répertoires :
my_list.txt
:
/tmp
/var/tmp
J'aimerais vérifier dans Bash avant d'ajouter un nom de répertoire si ce nom existe déjà dans le fichier.
grep -Fxq "$FILENAME" my_list.txt
Le statut de sortie est 0 (vrai) si le nom a été trouvé, 1 (faux) si non, donc :
if grep -Fxq "$FILENAME" my_list.txt
then
# code if found
else
# code if not found
fi
Voici les sections pertinentes de la page de manuel de grep
:
grep [options] PATTERN [FILE...]
-F
,--fixed-strings
Interprétez PATTERN comme une liste de chaînes de caractères fixes, séparées par des retours à la ligne, dont l'une d'entre elles doit être comparée.
-x
,--line-regexp
Sélectionnez uniquement les correspondances qui correspondent exactement à la ligne entière.
-q
,--quiet
,--silent
Quiet ; n'écrit rien sur la sortie standard. Sortir immédiatement avec le statut zéro si une correspondance est trouvée, même si une erreur a été détectée. Voir également l'option
-s
ou--no-messages
option.
Comme cela a été souligné à juste titre dans les commentaires, l'approche ci-dessus traite silencieusement les cas d'erreur comme si la chaîne était trouvée. Si vous souhaitez traiter les erreurs d'une manière différente, vous devrez omettre l'élément -q
et détecter les erreurs en fonction de l'état de sortie :
Normalement, l'état de sortie est 0 si les lignes sélectionnées sont trouvées et 1 sinon. Mais l'état de sortie est 2 si une erreur s'est produite, à moins que la commande
-q
ou--quiet
ou--silent
est utilisée et une ligne sélectionnée est trouvée. Notez cependant que POSIX impose seulement, pour des programmes tels quegrep
,cmp
etdiff
Il est donc conseillé, pour des raisons de portabilité, d'utiliser une logique qui teste cette condition générale au lieu d'une stricte égalité avec 2.
Pour supprimer la sortie normale de grep
vous pouvez le rediriger vers /dev/null
. Notez que l'erreur standard reste non dirigée, donc tout message d'erreur qui grep
pourrait s'afficher sur la console comme vous le souhaitez.
Pour gérer les trois cas, nous pouvons utiliser une case
déclaration :
case `grep -Fx "$FILENAME" "$LIST" >/dev/null; echo $?` in
0)
# code if found
;;
1)
# code if not found
;;
*)
# code if an error occurred
;;
esac
@Toren Le statut de sortie le plus récent peut être consulté en utilisant $?
. vous pouvez également utiliser la commande grep en plus de la commande if
(comme indiqué dans la réponse actualisée).
Vous pouvez utiliser grep -Fqx "$FILENAME"
et vous n'avez pas à vous soucier des caractères regex dans le contenu des variables et vous n'aurez pas à les utiliser dans la chaîne de recherche.
Concernant la solution suivante :
grep -Fxq "$FILENAME" my_list.txt
Au cas où vous vous demanderiez (comme moi) ce qu'est la -Fxq
signifie en clair :
F
: Affecte la façon dont PATTERN est interprété (chaîne fixe au lieu d'une regex)x
: Correspondre à la ligne entièreq
: Shhhhh... impression minimaleÀ partir du fichier de manuel :
-F, --fixed-strings
Interpret PATTERN as a list of fixed strings, separated by newlines, any of which is to be matched.
(-F is specified by POSIX.)
-x, --line-regexp
Select only those matches that exactly match the whole line. (-x is specified by POSIX.)
-q, --quiet, --silent
Quiet; do not write anything to standard output. Exit immediately with zero status if any match is
found, even if an error was detected. Also see the -s or --no-messages option. (-q is specified by
POSIX.)
Trois méthodes dans mon esprit :
1) Test court pour un nom dans un chemin (je ne suis pas sûr que ce soit votre cas)
ls -a "path" | grep "name"
2) Test court pour une chaîne de caractères dans un fichier
grep -R "string" "filepath"
3) Plus long bash script utilisant regex :
#!/bin/bash
declare file="content.txt"
declare regex="\s+string\s+"
declare file_content=$( cat "${file}" )
if [[ " $file_content " =~ $regex ]] # please note the space before and after the file content
then
echo "found"
else
echo "not found"
fi
exit
Cela devrait être plus rapide si vous avez pour tester plusieurs chaînes sur un fichier le contenu en utilisant une boucle, par exemple en changeant la regex à tout moment.
Si j'ai bien compris votre question, ceci devrait faire ce dont vous avez besoin.
En une ligne : check="/tmp/newdirectory"; [[ -n $(grep "^$check\$" my_list.txt) ]] && echo "dir already listed" || echo "$check" >> my_list.txt
Vous n'avez pas besoin de tester la sortie de grep, vous pouvez simplement utiliser grep -q
et appeler grep directement depuis if
comme le fait Thomas dans sa réponse. De plus, la question n'incluait pas de vérifier si le répertoire existe avant de l'ajouter à la liste (il pourrait s'agir d'une liste de répertoires supprimés, après tout).
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
0 votes
Pour trouver toutes les chaînes de caractères d'un fichier, vous pouvez exécuter grep dans une boucle FOR : unix.stackexchange.com/a/462445/43233