Comando para mostrar un mensaje arbitrario si existe un archivo en particular

11

¿Existe un comando para mostrar el mensaje "Sí" si existe un archivo en particular? No es necesario dar funcionalidad si el archivo no existe.

James
fuente

Respuestas:

25

Utilice este sencillo Bash one-liner:

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

La -everificación se evalúa como verdadera si FILENAMEexiste, sin importar cuál sea (archivo, directorio, enlace, dispositivo, ...).

Si solo desea verificar los archivos normales, use -fen su lugar, como dijo @Arronical .

Byte Commander
fuente
18
[ -e FILENAME ] && echo Yes
Zeb McCorkle
@ZebMcCorkle Correcto, eso también funciona. Puede publicar eso como respuesta separada.
Byte Commander
3
Si FILENAMEes una expansión variable o contiene caracteres especiales, no olvide citarla. por ejemplo, en un guión, [ -e "$1" ] && echo Yes.
Peter Cordes
@PeterCordes si está usando bash puede usar [[y en ]]lugar de citar la variable.
Holloway
1
@Holloway: sí, pero a veces necesitas escribir scripts portátiles que solo requieren POSIX sh. Es por eso que di una versión segura de esto en lugar de rechazarlo y votar la respuesta bash. También tenga en cuenta que no es un problema citar expansiones en el interior [[ ]], siempre es un buen hábito para los principiantes que no recuerdan las reglas especiales para dentro del [[ ]]operador, o para contextos aritméticos.
Peter Cordes
10

Puedes usar este simple script:

#!/bin/bash

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

Guárdalo como file-exists.sh. Luego, en la Terminal, escriba chmod +x file-exists.sh.

Úselo como: ./file-exists.sh FILEdonde reemplaza FILEcon el archivo que desea verificar, por ejemplo:

./file-exists.sh file.txt

Si file.txtexiste, Yesse imprimirá en la Terminal y el programa saldrá con el estado 0 (correcto). Si el archivo no existe, no se imprimirá nada y el programa saldrá con el estado 1 (error).

Si tienes curiosidad por qué incluí el exitcomando, sigue leyendo ...


¿Qué pasa con el exitcomando?

exitprovoca la terminación normal del proceso. Lo que esto significa es, básicamente: detiene el script. Acepta un parámetro opcional (numérico) que será el estado de salida del script que lo llamó.

Este estado de salida permite que sus otros scripts utilicen su file-existsscript y es su forma de saber si el archivo existe o no.

Un ejemplo simple que pone esto en uso es este script (guárdelo 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

Haga lo habitual chmod +x file-exists-cli.shy luego ejecutarlo: ./file-exists-cli.sh. Verás algo como esto:

El archivo 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

El archivo no 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
fuente
2
Bien, pero citarás referencias variables como "$1". Si tiene espacio en blanco, se romperá sin comillas y pueden ocurrir otras cosas malas.
Joe
9

En el shell bash en la línea de comando.

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

Esto utiliza el operador condicional bash -fy verifica si el archivo existe y si es un archivo normal. Si desea probar cualquier archivo, incluidos directorios y enlaces, utilice -e.

Este es un gran recurso para los condicionales de bash.

Arronico
fuente
1
¿Por qué las llaves dobles?
Byte Commander
1
No soy fanático de testsu formato original, sé que es excesivo, pero es un hábito mío.
Arronical
77
@ByteCommander: las llaves dobles son generalmente mejores que las llaves simples. Forman parte de la sintaxis de shell (en lugar de invocar el [comando, que generalmente se llama un builtin incorporado). Corrigen las inconsistencias y los comportamientos tontos de la versión de llave simple. El [incorporado permanece por compatibilidad, pero no veo ninguna buena razón para usarlo en el nuevo código bash. (Si necesita escribir scripts compatibles con POSIX que puedan ejecutarse en shells antiguos o algo así, eso es diferente.)
Nick Matteo
@kundor: Sin embargo, para ser justos, la mayoría de las veces acordadas [son dudosas. type -a [para mí enumera "shell incorporado", luego " /usr/bin/[."
wchargin
1
@wchargin: Me temo que no entiendo a qué te refieres. Sus typeresultados parecen corroborar lo que dije, ¿no?
Nick Matteo
5

El comando más corto para hacer lo que quieres es:

test -e FILENAME && echo Yes

test -eprobará si el nombre dado existe en el sistema de archivos. (Puede usar test -fpara restringir solo a archivos normales. Consulte man testpara obtener más información).

Si la condición dada se evalúa como verdadera, testdevuelve un estado de salida exitoso (de lo contrario, devuelve un estado de falla). Combinamos los dos comandos usando &&, lo que significa "ejecutar el siguiente comando si el comando anterior salió con un estado de éxito". El siguiente comando simplemente imprime Yesen la salida estándar; en el caso de un shell interactivo, en el terminal.

Esto evita el material textual adicional de una ifdeclaración, pero da el mismo resultado. Usar &&(o su opuesto ||) para vincular comandos funciona bien cuando solo se trata de un comando. Si desea hacer más que ejecutar un solo comando en respuesta al estado de salida de un solo comando, el uso de la ifsintaxis se vuelve mucho más legible rápidamente.

Como ya se señaló en otras respuestas, la ifconstrucción de estilo equivalente sería:

if test -e FILENAME; then echo Yes; fi

o alternativamente:

if test -e FILENAME
then
    echo Yes
fi

Para estos fines, [y testson equivalentes, excepto que [exige una terminación ].

un CVn
fuente
4

Para cubrir este tipo de preguntas, hay varias formas, y aquí hay otra: use el findcomando con -execbandera. La ruta al archivo se puede dividir en dos partes find /etcque establece el directorio y -name FILENAMEque especifica el nombre del archivo (¡duh!). -maxdepthseguirá findtrabajando /etcsolo con el directorio y no descenderá a subdirectorios

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:~$ 

Otra forma, a través de stat:

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

Y alternativamente a través de 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'

O una alternativa de línea de comando corta:

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