Ho un file che contiene i nomi di directory:
my_list.txt
:
/tmp
/var/tmp
Vorrei controllare Bash prima di aggiungere un nome di directory se quel nome esiste già nel file.
Ho un file che contiene i nomi di directory:
my_list.txt
:
/tmp
/var/tmp
Vorrei controllare Bash prima di aggiungere un nome di directory se quel nome esiste già nel file.
Risposte:
grep -Fxq "$FILENAME" my_list.txt
Lo stato di uscita è 0 (vero) se il nome è stato trovato, 1 (falso) in caso contrario, quindi:
if grep -Fxq "$FILENAME" my_list.txt
then
# code if found
else
# code if not found
fi
Ecco le sezioni rilevanti della pagina man pergrep
:
grep [options] PATTERN [FILE...]
-F
,--fixed-strings
Interpreta PATTERN come un elenco di stringhe fisse, separate da newline, ognuna delle quali deve essere abbinata.
-x
,--line-regexp
Seleziona solo quelle corrispondenze che corrispondono esattamente all'intera riga.
-q
,--quiet
,--silent
Silenzioso; non scrivere nulla sullo standard output. Esci immediatamente con stato zero se viene rilevata una corrispondenza, anche se è stato rilevato un errore. Vedi anche l' opzione
-s
o--no-messages
.
Come giustamente sottolineato nei commenti, l'approccio sopra tratta silenziosamente i casi di errore come se fosse trovata la stringa. Se desideri gestire gli errori in modo diverso, dovrai omettere l' -q
opzione e rilevare gli errori in base allo stato di uscita:
Normalmente, lo stato di uscita è 0 se vengono trovate le linee selezionate e 1 altrimenti. Ma lo stato di uscita è 2 se si è verificato un errore, a meno che non venga utilizzata l'opzione
-q
o--quiet
o--silent
e venga trovata una linea selezionata. Si noti, tuttavia, che POSIX mandati solo, per programmi comegrep
,cmp
ediff
che lo stato di uscita in caso di errore sia maggiore di 1; è quindi consigliabile, per motivi di portabilità, utilizzare la logica che verifica questa condizione generale anziché la rigorosa uguaglianza con 2.
Per sopprimere l'output normale da grep
, è possibile reindirizzarlo a /dev/null
. Si noti che l'errore standard rimane non indirizzato, quindi tutti i messaggi di errore che grep
potrebbero essere stampati finiranno sulla console come si vorrebbe.
Per gestire i tre casi, possiamo usare case
un'istruzione:
case `grep -Fx "$FILENAME" "$LIST" >/dev/null; echo $?` in
0)
# code if found
;;
1)
# code if not found
;;
*)
# code if an error occurred
;;
esac
$?
. puoi anche usare il comando grep accanto if
all'istruzione (come mostrato nella risposta aggiornata).
grep -Fqx "$FILENAME"
e non devi preoccuparti dei caratteri regex nei contenuti delle variabili e non dovrai usarli nella stringa di ricerca.
-q / --silent
necessario? Dice falsamente "tutto bene" per colpire anche se si verifica un errore. Se ho capito bene. Sembra un concetto imperfetto per questo caso.
Per quanto riguarda la seguente soluzione:
grep -Fxq "$FILENAME" my_list.txt
Nel caso ti stia chiedendo (come ho fatto io) cosa -Fxq
significa in parole povere:
F
: Influisce sull'interpretazione di PATTERN (stringa fissa anziché regex)x
: Abbina l'intera rigaq
: Shhhhh ... stampa minimaDal file 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.)
Tre metodi nella mia mente:
1) Breve test per un nome in un percorso (non sono sicuro che questo potrebbe essere il tuo caso)
ls -a "path" | grep "name"
2) Breve test per una stringa in un file
grep -R "string" "filepath"
3) Script bash più lungo usando 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
Questo dovrebbe essere più veloce se devi testare più stringhe su un contenuto di file usando un loop, ad esempio cambiando la regex in qualsiasi ciclo.
Modo più semplice:
if grep "$filename" my_list.txt > /dev/null
then
... found
else
... not found
fi
Suggerimento: invia a /dev/null
se si desidera lo stato di uscita del comando, ma non gli output.
-q
stesso di --quiet
:)
-q
anche sulla migliore risposta qui, ed è il quarto posto. nessuna giustizia in questo mondo.
Il modo più semplice e semplice sarebbe:
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 restituirà il conteggio di quante volte si verifica la stringa nel file.
Se ho capito correttamente la tua domanda, questo dovrebbe fare quello che ti serve.
In una riga :check="/tmp/newdirectory"; [[ -n $(grep "^$check\$" my_list.txt) ]] && echo "dir already listed" || echo "$check" >> my_list.txt
grep -q
e chiamare grep direttamente da if
come Thomas fa nella sua risposta. Inoltre, la domanda non includeva il controllo dell'esistenza della directory prima di aggiungerla all'elenco (potrebbe essere un elenco di directory eliminate, dopo tutto).
grep -E "(string)" /path/to/file || echo "no match found"
-L'opzione fa in modo che grep usi espressioni regolari
La soluzione di @ Thomas non ha funzionato per me per qualche motivo, ma avevo una stringa più lunga con caratteri speciali e spazi bianchi, quindi ho cambiato i parametri in questo modo:
if grep -Fxq 'string you want to find' "/path/to/file"; then
echo "Found"
else
echo "Not found"
fi
Spero che aiuti qualcuno
Una soluzione senza grep, funziona per me:
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
basato su: https://stackoverflow.com/a/229606/3306354
grep -q
descritto nella risposta accettata è l'approccio più efficiente.
grep -Fxq "String to be found" | ls -a