Comando para exibir uma mensagem arbitrária se existir um arquivo específico

11

Existe um comando para exibir a mensagem "Sim" se um arquivo específico existir? Não há necessidade de fornecer funcionalidade se o arquivo não existir.

James
fonte

Respostas:

25

Use esta linha única simples do Bash:

if [ -e FILENAME ] ; then echo Yes ; fi

A -everificação é avaliada como verdadeira se FILENAMEexistir, não importa o que seja (arquivo, diretório, link, dispositivo, ...).

Se você quiser apenas verificar arquivos regulares, use-o -fcomo disse a @Arronical .

Byte Commander
fonte
18
[ -e FILENAME ] && echo Yes
Zeb McCorkle
@ZebMcCorkle Correto, isso também funciona. Você pode postar isso como resposta separada.
Byte Commander
3
Se FILENAMEfor uma expansão variável ou contiver caracteres especiais, não esqueça de citá-la. por exemplo, em um script [ -e "$1" ] && echo Yes.
Peter Cordes
@ PeterCordes, se você estiver usando o bash, poderá usar [[e, em ]]vez de citar a variável.
Holloway
1
@ Hollow: sim, mas às vezes você precisa escrever scripts portáteis que exigem apenas o POSIX sh. Foi por isso que dei uma versão segura disso, em vez de diminuir o voto e votar a resposta do bash. Observe também que não é um problema citar expansões internas [[ ]], sempre citar é um bom hábito para iniciantes que não se lembram das regras especiais para dentro do [[ ]]operador ou para contextos aritméticos.
Peter Cordes
10

Você pode usar este script simples:

#!/bin/bash

if [[ -f $1 ]]; then
    echo "Yes"
    exit 0
else
    exit 1
fi

Salve como file-exists.sh. Em seguida, no terminal, digite chmod +x file-exists.sh.

Use-o como: ./file-exists.sh FILEonde você substitui FILEpelo arquivo que deseja verificar, por exemplo:

./file-exists.sh file.txt

Se file.txtexistir, Yesserá impresso no terminal e o programa sairá com o status 0 (êxito). Se o arquivo não existir, nada será impresso e o programa sairá com o status 1 (falha).

Se você está curioso para saber por que eu incluí o exitcomando, continue lendo ...


O que há com o exitcomando?

exitcausa o término normal do processo. O que isso significa é, basicamente: ele interrompe o script. Ele aceita um parâmetro opcional (numérico) que será o status de saída do script que o chamou.

Esse status de saída permite que seus outros scripts usem seu file-existsscript e é a maneira deles de saber se o arquivo existe ou não.

Um exemplo simples que coloca isso em uso é esse script (salve-o como file-exists-cli.sh):

#!/bin/bash

echo "Enter a filename and I will tell you if it exists or not: "
read FILE
# Run `file-exists.sh` but discard any output because we don't need it in this example
./file-exists.sh $FILE &>> /dev/null
# #? is a special variable that holds the exit status of the previous command
if [[ $? == 0 ]]; then
    echo "$FILE exists"
else
    echo "$FILE does not exist"
fi

Faça o habitual chmod +x file-exists-cli.she, em seguida, executá-lo: ./file-exists-cli.sh. Você verá algo assim:

O arquivo existe ( exit 0):

➜  ~ ./file-exists-cli.sh 
Enter a filename and I will tell you if it exists or not: 
booleans.py
booleans.py exists

O arquivo não existe ( exit 1):

➜  ~ ./file-exists-cli.sh
Enter a filename and I will tell you if it exists or not: 
asdf
asdf does not exist
grooveplex
fonte
2
Bom, mas citarás referências de variáveis ​​como "$1". Se houver espaço em branco, ele será quebrado sem aspas e outras coisas ruins podem acontecer.
Joe
9

No shell bash na linha de comando.

if [[ -f /path/to/file ]]; then echo "Yes"; fi

Isso usa o operador condicional do bash -fe está verificando se o arquivo existe e é um arquivo regular. Se você deseja testar qualquer arquivo, incluindo diretórios e links, use -e.

Este é um ótimo recurso para condicionais do bash.

Arronical
fonte
1
Por que as chaves duplas?
Byte Commander
1
Não sou fã testno formato original, sei que é um exagero, mas é um hábito meu.
Arronical
7
@ ByteCommander: chaves duplas são geralmente melhores do que chaves simples. Eles fazem parte da sintaxe do shell (em vez de chamar o [comando, que geralmente chama de embutido.) Eles corrigem inconsistências e comportamentos mudos da versão de chave única. O [builtin permanece para compatibilidade, mas não vejo nenhuma boa razão para usá-lo no novo código bash. (Se você precisar escrever scripts POSIX que podem ser executados em escudos antigos ou algo assim, isso é diferente.)
Nick Matteo
@ kundor: Mas, em geral, concordar em ser justo " [geralmente chama de embutido" é dúbio. type -a [para mim lista "shell embutido" e depois " /usr/bin/[."
wchargin
1
@chargin: Receio não entender o que você está falando. Seus typeresultados parecem corroborar o que eu disse, não?
Nick Matteo
5

O comando mais curto para fazer o que você deseja é:

test -e FILENAME && echo Yes

test -etestará se o nome fornecido existe no sistema de arquivos. (Você pode usar test -fpara restringir apenas a arquivos regulares. Veja man testpara mais.)

Se a condição fornecida for avaliada como verdadeira, testretornará um status de saída bem-sucedido (caso contrário, retornará um status de falha). Combinamos os dois comandos usando &&, o que significa "executar o próximo comando se o comando anterior sair com um status de sucesso". O próximo comando simplesmente imprime Yesna saída padrão; no caso de um shell interativo, no terminal.

Isso evita o material textual adicional de uma ifdeclaração, mas fornece o mesmo resultado. Usar &&(ou seu oposto ||) para amarrar comandos funciona bem quando apenas um único comando está envolvido. Se você deseja fazer mais do que executar um único comando em resposta ao status de saída de um único comando, o uso da ifsintaxe rapidamente se torna muito mais legível.

Como já apontado em outras respostas, a ifconstrução de estilo equivalente seria:

if test -e FILENAME; then echo Yes; fi

ou alternativamente:

if test -e FILENAME
then
    echo Yes
fi

Para esses fins, [e testsão equivalentes, exceto que [exige uma rescisão ].

um CVn
fonte
4

Para abordar esse tipo de pergunta, há várias maneiras, e aqui está outra: use findcommand com -execflag. O caminho para o arquivo pode ser dividido em duas partes, find /etcque define o diretório e -name FILENAMEespecifica o nome do arquivo (duh!). -maxdepthcontinuará findtrabalhando /etcapenas com o diretório e não descerá em subdiretórios

adminx@L455D:~$ find /etc -maxdepth 1  -name passwd -exec printf "YES\n" \;
YES
adminx@L455D:~$ find /etc -maxdepth 1  -name passwd1 -exec printf "YES\n" \;
adminx@L455D:~$ 

Outra maneira, via stat:

adminx@L455D:~$ stat /etc/passwd1 &>/dev/null && echo YES
adminx@L455D:~$ stat /etc/passwd &>/dev/null && echo YES
YES

E, alternativamente, via python:

>>> import os
>>> if os.stat('/etc/passwd'): 
...    print 'YES'
... 
YES
>>> if os.stat('/etc/passwd1'): 
...    print 'YES'
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 2] No such file or directory: '/etc/passwd1'

Ou uma alternativa curta à linha de comando:

 python -c "from os.path import exists; print 'Yes' if exists('/etc/fstab') else '' "
Sergiy Kolodyazhnyy
fonte