Eu tenho um arquivo que contém nomes de diretório:
my_list.txt
:
/tmp
/var/tmp
Gostaria de fazer check-in no Bash antes de adicionar um nome de diretório, se esse nome já existir no arquivo.
Eu tenho um arquivo que contém nomes de diretório:
my_list.txt
:
/tmp
/var/tmp
Gostaria de fazer check-in no Bash antes de adicionar um nome de diretório, se esse nome já existir no arquivo.
Respostas:
grep -Fxq "$FILENAME" my_list.txt
O status de saída é 0 (verdadeiro) se o nome foi encontrado, 1 (falso) se não, então:
if grep -Fxq "$FILENAME" my_list.txt
then
# code if found
else
# code if not found
fi
Aqui estão as seções relevantes da página de manual paragrep
:
grep [options] PATTERN [FILE...]
-F
,--fixed-strings
Interprete PATTERN como uma lista de cadeias fixas, separadas por novas linhas, qualquer uma das quais deve ser correspondida.
-x
,--line-regexp
Selecione apenas as correspondências que correspondam exatamente à linha inteira.
-q
,--quiet
,--silent
Quieto; não escreva nada na saída padrão. Saia imediatamente com o status zero se alguma correspondência for encontrada, mesmo que um erro tenha sido detectado. Veja também a opção
-s
ou--no-messages
.
Como corretamente apontado nos comentários, a abordagem acima trata silenciosamente os casos de erro como se a sequência fosse encontrada. Se você deseja lidar com erros de uma maneira diferente, precisará omitir a -q
opção e detectar erros com base no status de saída:
Normalmente, o status de saída é 0 se as linhas selecionadas forem encontradas e 1 caso contrário. Mas o status de saída é 2 se ocorrer um erro, a menos que a opção
-q
ou--quiet
ou--silent
seja usada e uma linha selecionada seja encontrada. Note, no entanto, que POSIX apenas mandatos, para programas comogrep
,cmp
ediff
que o status de saída em caso de erro ser maior do que 1; portanto, é recomendável, por uma questão de portabilidade, usar a lógica que testa essa condição geral em vez da estrita igualdade com 2.
Para suprimir a saída normal de grep
, você pode redirecioná-la para /dev/null
. Observe que o erro padrão permanece sem direcionamento; portanto, qualquer mensagem de erro que grep
possa ser impressa será finalizada no console como você provavelmente desejaria.
Para lidar com os três casos, podemos usar uma case
declaração:
case `grep -Fx "$FILENAME" "$LIST" >/dev/null; echo $?` in
0)
# code if found
;;
1)
# code if not found
;;
*)
# code if an error occurred
;;
esac
$?
. você também pode usar o comando grep ao lado da if
instrução (como mostrado na resposta atualizada).
grep -Fqx "$FILENAME"
e não precisa se preocupar com caracteres regex no conteúdo da variável e não precisará usá-los na string de pesquisa.
-q / --silent
é necessário? Diz falsamente "tudo de bom" para bater, mesmo que ocorra um erro. Se eu entendi direito. Parece um conceito defeituoso para este caso.
Em relação à seguinte solução:
grep -Fxq "$FILENAME" my_list.txt
Caso você esteja se perguntando (como eu) o que -Fxq
significa em inglês simples:
F
: Afeta como PATTERN é interpretado (sequência fixa em vez de uma expressão regular)x
: Corresponder a linha inteiraq
: Shhhhh ... impressão mínimaNo arquivo 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.)
Três métodos em minha mente:
1) Teste curto para um nome em um caminho (não tenho certeza se esse pode ser o seu caso)
ls -a "path" | grep "name"
2) Teste curto para uma string em um arquivo
grep -R "string" "filepath"
3) Script bash mais longo 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
Isso deve ser mais rápido se você precisar testar várias strings em um conteúdo de arquivo usando um loop, por exemplo, alterando a regex em qualquer ciclo.
Maneira mais simples:
if grep "$filename" my_list.txt > /dev/null
then
... found
else
... not found
fi
Dica: envie para /dev/null
se desejar o status de saída do comando, mas não as saídas.
-q
que é o mesmo que --quiet
:)
-q
melhor resposta também aqui e é o quarto lugar. não há justiça neste mundo.
A maneira mais fácil e simples seria:
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 retornará a contagem de quantas vezes a string ocorre no arquivo.
Se entendi sua pergunta corretamente, isso deve fazer o que você precisa.
Em uma linha :check="/tmp/newdirectory"; [[ -n $(grep "^$check\$" my_list.txt) ]] && echo "dir already listed" || echo "$check" >> my_list.txt
grep -q
e chamar o grep diretamente, if
como Thomas faz em sua resposta. Além disso, a pergunta não incluiu a verificação da existência do diretório antes de adicioná-lo à lista (afinal, poderia ser uma lista de diretórios excluídos).
grep -E "(string)" /path/to/file || echo "no match found"
A opção -E faz com que o grep use expressões regulares
A solução do @ Thomas não funcionou para mim por algum motivo, mas eu tinha uma string mais longa com caracteres especiais e espaços em branco, então apenas alterei os parâmetros assim:
if grep -Fxq 'string you want to find' "/path/to/file"; then
echo "Found"
else
echo "Not found"
fi
Espero que ajude alguém
Uma solução grep-less funciona para mim:
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
baseado em: https://stackoverflow.com/a/229606/3306354
grep -q
descrito na resposta aceita é a abordagem mais eficiente.
grep -Fxq "String to be found" | ls -a
ls
aceita entrada padrão?