J'ai un fichier qui contient des noms de répertoire:
my_list.txt
:
/tmp
/var/tmp
Je voudrais archiver Bash avant d'ajouter un nom de répertoire si ce nom existe déjà dans le fichier.
J'ai un fichier qui contient des noms de répertoire:
my_list.txt
:
/tmp
/var/tmp
Je voudrais archiver Bash avant d'ajouter un nom de répertoire si ce nom existe déjà dans le fichier.
Réponses:
grep -Fxq "$FILENAME" my_list.txt
Le statut de sortie est 0 (vrai) si le nom a été trouvé, 1 (faux) sinon, 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 pourgrep
:
grep [options] PATTERN [FILE...]
-F
,--fixed-strings
Interprétez PATTERN comme une liste de chaînes fixes, séparées par des sauts de ligne, dont chacune doit être mise en correspondance.
-x
,--line-regexp
Sélectionnez uniquement les correspondances qui correspondent exactement à toute la ligne.
-q
,--quiet
,--silent
Silencieux; n'écrivez rien sur la sortie standard. Quittez immédiatement avec l'état 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
.
Comme indiqué à juste titre dans les commentaires, l'approche ci-dessus traite silencieusement les cas d'erreur comme si la chaîne avait été trouvée. Si vous souhaitez gérer les erreurs d'une manière différente, vous devrez omettre l' -q
option et détecter les erreurs en fonction de l'état de sortie:
Normalement, l'état de sortie est 0 si des lignes sélectionnées sont trouvées et 1 sinon. Mais l'état de sortie est 2 si une erreur s'est produite, sauf si l' option
-q
ou--quiet
ou--silent
est utilisée et qu'une ligne sélectionnée est trouvée. Notez toutefois que seuls les mandats, POSIX pour des programmes tels quegrep
,cmp
etdiff
que l'état de sortie en cas d'erreur soit supérieur à 1; 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 la rediriger vers /dev/null
. Notez que l'erreur standard reste non dirigée, donc tous les messages d'erreur qui grep
pourraient s'imprimer se retrouveront sur la console comme vous le voudriez probablement.
Pour gérer les trois cas, nous pouvons utiliser une case
instruction:
case `grep -Fx "$FILENAME" "$LIST" >/dev/null; echo $?` in
0)
# code if found
;;
1)
# code if not found
;;
*)
# code if an error occurred
;;
esac
$?
. vous pouvez également utiliser la commande grep à côté de l' if
instruction (comme indiqué dans la réponse mise à jour).
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.
-q / --silent
besoin? Son dit faussement "tout va bien" à bash même si une erreur se produit. Si j'ai bien compris. Semble un concept défectueux pour ce cas.
Concernant la solution suivante:
grep -Fxq "$FILENAME" my_list.txt
Au cas où vous vous demandez (comme je l'ai fait) ce que -Fxq
signifie en anglais simple:
F
: Affecte la façon dont le motif est interprété (chaîne fixe au lieu d'une expression régulière)x
: Correspondre à toute la ligneq
: Shhhhh ... impression minimaleDepuis le fichier man:
-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) Court test pour un nom dans un chemin (je ne suis pas sûr que ce soit votre cas)
ls -a "path" | grep "name"
2) Court test pour une chaîne dans un fichier
grep -R "string" "filepath"
3) Script bash plus long utilisant l'expression régulière:
#!/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 devez tester plusieurs chaînes sur un contenu de fichier en utilisant une boucle, par exemple en changeant l'expression régulière à n'importe quel cicle.
Manière plus simple:
if grep "$filename" my_list.txt > /dev/null
then
... found
else
... not found
fi
Astuce: envoyez à /dev/null
si vous voulez l'état de sortie de la commande, mais pas les sorties.
-q
même chose que --quiet
:)
-q
meilleure réponse également ici, et est la quatrième place. pas de justice dans ce monde.
Le moyen le plus simple et le plus simple serait:
isInFile=$(cat file.txt | grep -c "string")
if [ $isInFile -eq 0 ]; then
#string not contained in file
else
#string is in file at least once
fi
grep -c renverra le nombre de fois où la chaîne se produit dans le fichier.
Si j'ai bien compris votre question, cela devrait faire ce dont vous avez besoin.
En une seule ligne :check="/tmp/newdirectory"; [[ -n $(grep "^$check\$" my_list.txt) ]] && echo "dir already listed" || echo "$check" >> my_list.txt
grep -q
et appeler grep directement if
comme Thomas le fait dans sa réponse. De plus, la question ne comprenait 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).
grep -E "(string)" /path/to/file || echo "no match found"
L'option -E oblige grep à utiliser des expressions régulières
La solution de @ Thomas n'a pas fonctionné pour moi pour une raison quelconque, mais j'avais une chaîne plus longue avec des caractères spéciaux et des espaces, donc j'ai juste changé les paramètres comme ceci:
if grep -Fxq 'string you want to find' "/path/to/file"; then
echo "Found"
else
echo "Not found"
fi
J'espère que cela aide quelqu'un
Une solution sans grep, fonctionne pour moi:
MY_LIST=$( cat /path/to/my_list.txt )
if [[ "${MY_LIST}" == *"${NEW_DIRECTORY_NAME}"* ]]; then
echo "It's there!"
else
echo "its not there"
fi
grep -q
décrit dans la réponse acceptée est l'approche la plus efficace.
grep -Fxq "String to be found" | ls -a