Un comando no devuelve una cadena (devuelve un código de salida entero pequeño, generalmente 0 para el éxito y 1 o 2 en caso de error), pero puede generar algunos datos para poner en una cadena.
Basile Starynkevitch
@BasileStarynkevitch esto es lo que necesito. Sé que el comando devuelve el código de salida. Pero el código de salida de mis comandos siempre es 0. Entonces necesito controlar la salida
Anteriormente, la pregunta preguntaba cómo verificar si hay archivos en un directorio. El siguiente código logra eso, pero vea la respuesta de rsp para una mejor solución.
Salida vacía
Los comandos no devuelven valores, los generan. Puede capturar esta salida utilizando la sustitución de comandos ; por ej $(ls -A). Puede probar una cadena no vacía en Bash como esta:
if[[ $(ls -A)]];then
echo "there are files"else
echo "no files found"fi
Tenga en cuenta que he usado en -Alugar de -a, ya que omite las entradas simbólicas de directorio actual ( .) y padre ( ..).
Nota: Como se señaló en los comentarios, la sustitución de comandos no captura las nuevas líneas finales . Por lo tanto, si el comando genera solo nuevas líneas, la sustitución no capturará nada y la prueba devolverá falso. Si bien es poco probable, esto es posible en el ejemplo anterior, ya que una nueva línea es un nombre de archivo válido. Más información en esta respuesta .
Código de salida
Si desea comprobar que el comando se completó correctamente, puede inspeccionar $?, que contiene el código de salida del último comando (cero para el éxito, no cero para el fracaso). Por ejemplo:
Puede omitir-n , por lo que será soloif [[ $(ls -A) ]]; then
usuario
66
Este método da falso para los comandos que generan solo nuevas líneas.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
89
TL; DR
if [[ $(ls -A | head -c1 | wc -c) -ne 0 ]]; then ...; fi
Gracias a netj
por una sugerencia para mejorar mi original: if [[ $(ls -A | wc -c) -ne 0 ]]; then ...; fi
Esta es una vieja pregunta, pero veo al menos dos cosas que necesitan alguna mejora o al menos alguna aclaración.
Primer problema
El primer problema que veo es que la mayoría de los ejemplos proporcionados aquí simplemente no funcionan . Utilizan los comandos ls -aly ls -Al, que generan cadenas no vacías en directorios vacíos. Esos ejemplos siempre informan que hay archivos, incluso cuando no hay ninguno .
Por esa razón, debe usar solo ls -A: ¿por qué alguien querría usar el -linterruptor que significa "usar un formato de listado largo" cuando todo lo que quiere es probar si hay alguna salida o no?
Entonces, la mayoría de las respuestas aquí son simplemente incorrectas.
Segundo problema
El segundo problema es que, si bien algunas respuestas funcionan bien (los que no utilizan ls -alo ls -Al, pero ls -Aen su lugar) todos hacen algo como esto:
ejecuta un comando
amortigua toda su salida en RAM
convertir la salida en una gran cadena de una sola línea
compara esa cadena con una cadena vacía
Lo que sugeriría hacer en su lugar sería:
ejecuta un comando
cuente los caracteres en su salida sin almacenarlos
o incluso mejor: cuente el número máximo de 1 carácter using head -c1 (gracias a netj por publicar esta idea en los comentarios a continuación)
compara ese número con cero
Entonces, por ejemplo, en lugar de:
if[[ $(ls -A)]]
Yo usaría:
if[[ $(ls -A | wc -c)-ne 0]]# or:if[[ $(ls -A | head -c1 | wc -c)-ne 0]]
[[ $(... | head -c | wc -c) -gt 0 ]]o [[ -n $(... | head -c1) ]]son mejores porque wc -ctendrían que consumir toda la salida del comando.
netj
@netj Esta es una muy buena idea. Vea mi respuesta actualizada: agregué su sugerencia. ¡Muchas gracias!
rsp
¿Alguna idea sobre cómo obtener la salida?
fahrradflucht
Creo que el original (sin cabeza) es mejor en el caso general. ¡No siempre es una buena idea matar el comando tan pronto como comienza a escribir la salida!
stk
@stk La mayoría de los programas saldrán de manera segura después de recibir una señal de apagado.
Cambunctious
40
if[-z "$(ls -lA)"];then
echo "no files found"else
echo "There are files"fi
Esto ejecutará el comando y verificará si la salida (cadena) devuelta tiene una longitud cero. Es posible que desee consultar las páginas del manual de 'prueba' para otros indicadores.
Utilice el "" alrededor del argumento que se está comprobando, de lo contrario, los resultados vacíos generarán un error de sintaxis ya que no hay un segundo argumento (para verificar).
Nota: eso ls -lasiempre regresa .y, ..por lo tanto, usar eso no funcionará, consulte las páginas del manual de ls . Además, si bien esto puede parecer conveniente y fácil, supongo que se romperá fácilmente. ¡Escribir un pequeño script / aplicación que devuelve 0 o 1 dependiendo del resultado es mucho más confiable!
Es posible que prefiera usar en $(lugar de una cita inversa, porque $(anida mejor
Basile Starynkevitch
Tienes razón, es una mejor práctica usarlos siempre, aunque no necesitamos anidar aquí.
Veger
23
Para aquellos que desean una solución elegante, independiente de la versión bash (de hecho, debería funcionar en otros proyectiles modernos) y para aquellos que adoran usar frases ingeniosas para tareas rápidas. ¡Aquí vamos!
ls | grep .&& echo 'files found'|| echo 'files not found'
(tenga en cuenta como uno de los comentarios mencionados, ls -aly de hecho, solo -ly -atodos devolverán algo, por lo que en mi respuesta utilizo simplels
Si usa grep -q ^en su lugar, los caracteres de nueva línea también coincidirán, y grep no imprimirá nada en la salida estándar. Además, saldrá tan pronto como reciba cualquier entrada, en lugar de esperar a que finalice su flujo de entrada.
mortehu
Debería comenzar con ls -Asi desea incluir archivos de puntos (o directorios)
Esto no funciona: el comando lsnunca se ejecuta. Solo verifica si la expansión de la variableLS no está vacía.
gniourf_gniourf
1
@gniourf_gniourf: ¿qué te hace pensar eso? El encantamiento de backtick no es tan bonito o flexible como $ (), pero funciona ...
tink
El -aconmutador nunca devolverá ningún contenido (es decir, devolverá contenido si hay archivos o no) ya que siempre está presente lo implícito .y los ..directorios.
wrlee
3
Aquí hay una solución para casos más extremos:
if[`command | head -c1 | wc -c`-gt 0];then...;fi
Esto funcionará
para todos los proyectiles Bourne;
si la salida del comando es todos ceros;
eficientemente independientemente del tamaño de salida;
sin embargo,
el comando o sus subprocesos se eliminarán una vez que se envíe algo.
Todas las respuestas dadas hasta ahora tratan con comandos que terminan y generan una cadena no vacía.
La mayoría están rotos en los siguientes sentidos:
No manejan adecuadamente los comandos que generan solo nuevas líneas;
a partir de Bash≥4.4 la mayoría enviará un error estándar de spam si el comando genera bytes nulos (ya que usan la sustitución de comandos);
la mayoría sorberá la secuencia de salida completa, por lo que esperará hasta que el comando termine antes de responder. Algunos comandos nunca terminan (prueba, por ejemplo, yes).
Entonces, para solucionar todos estos problemas y responder la siguiente pregunta de manera eficiente,
¿Cómo puedo probar si un comando genera una cadena vacía?
También puede agregar un tiempo de espera para probar si un comando genera una cadena no vacía dentro de un tiempo determinado, utilizando readla -topción 's . Por ejemplo, por un tiempo de espera de 2.5 segundos:
Creo que esta respuesta es bastante poco apreciada. Estaba rendimiento de pruebas de algunas de las soluciones aquí usando 100 iteraciones para cada uno de 3 escenarios de entrada ( seq 1 10000000, seq 1 20y printf""). El único enfrentamiento que este enfoque de lectura no ganó fue con el -z "$(command)"enfoque de una entrada vacía. Incluso entonces, solo pierde alrededor del 10-15%. Parecen alcanzar el equilibrio seq 1 10. En cualquier caso, el -z "$(command)"enfoque se vuelve tan lento a medida que aumenta el tamaño de entrada que evitaría usarlo para cualquier entrada de tamaño variable.
abathur el
0
Aquí hay un enfoque alternativo que escribe el std-out y std-err de algún comando en un archivo temporal, y luego verifica si ese archivo está vacío. Una ventaja de este enfoque es que captura ambas salidas y no utiliza subcapas ni tuberías. Estos últimos aspectos son importantes porque pueden interferir con la captura del manejo de salida de bash (por ejemplo, aquí )
tmpfile=$(mktemp)
some-command &>"$tmpfile"if[[ $?!=0]];then
echo "Command failed"elif[[-s "$tmpfile"]];then
echo "Command generated output"else
echo "Command has no output"fi
rm -f "$tmpfile"
ifne
para esto. joeyh.name/code/moreutilsRespuestas:
Anteriormente, la pregunta preguntaba cómo verificar si hay archivos en un directorio. El siguiente código logra eso, pero vea la respuesta de rsp para una mejor solución.
Salida vacía
Los comandos no devuelven valores, los generan. Puede capturar esta salida utilizando la sustitución de comandos ; por ej
$(ls -A)
. Puede probar una cadena no vacía en Bash como esta:Tenga en cuenta que he usado en
-A
lugar de-a
, ya que omite las entradas simbólicas de directorio actual (.
) y padre (..
).Nota: Como se señaló en los comentarios, la sustitución de comandos no captura las nuevas líneas finales . Por lo tanto, si el comando genera solo nuevas líneas, la sustitución no capturará nada y la prueba devolverá falso. Si bien es poco probable, esto es posible en el ejemplo anterior, ya que una nueva línea es un nombre de archivo válido. Más información en esta respuesta .
Código de salida
Si desea comprobar que el comando se completó correctamente, puede inspeccionar
$?
, que contiene el código de salida del último comando (cero para el éxito, no cero para el fracaso). Por ejemplo:Más información aquí .
fuente
-n
, por lo que será soloif [[ $(ls -A) ]]; then
TL; DR
if [[ $(ls -A | head -c1 | wc -c) -ne 0 ]]; then ...; fi
Gracias a netj por una sugerencia para mejorar mi original:
if [[ $(ls -A | wc -c) -ne 0 ]]; then ...; fi
Esta es una vieja pregunta, pero veo al menos dos cosas que necesitan alguna mejora o al menos alguna aclaración.
Primer problema
El primer problema que veo es que la mayoría de los ejemplos proporcionados aquí simplemente no funcionan . Utilizan los comandos
ls -al
yls -Al
, que generan cadenas no vacías en directorios vacíos. Esos ejemplos siempre informan que hay archivos, incluso cuando no hay ninguno .Por esa razón, debe usar solo
ls -A
: ¿por qué alguien querría usar el-l
interruptor que significa "usar un formato de listado largo" cuando todo lo que quiere es probar si hay alguna salida o no?Entonces, la mayoría de las respuestas aquí son simplemente incorrectas.
Segundo problema
El segundo problema es que, si bien algunas respuestas funcionan bien (los que no utilizan
ls -al
ols -Al
, perols -A
en su lugar) todos hacen algo como esto:Lo que sugeriría hacer en su lugar sería:
using head -c1
(gracias a netj por publicar esta idea en los comentarios a continuación)
Entonces, por ejemplo, en lugar de:
Yo usaría:
En vez de:
Yo usaría:
y así.
Para salidas pequeñas puede que no sea un problema, pero para salidas más grandes la diferencia puede ser significativa:
Compáralo con:
Y aún mejor:
Ejemplo completo
Ejemplo actualizado de la respuesta de Will Vousden:
Actualizado nuevamente después de las sugerencias de netj :
Actualización adicional de jakeonfire :
grep
saldrá con una falla si no hay coincidencia. Podemos aprovechar esto para simplificar ligeramente la sintaxis:Descartando espacios en blanco
Si el comando que está probando podría generar algún espacio en blanco que desea tratar como una cadena vacía, entonces en lugar de:
podrías usar:
o con
head -c1
:o algo así.
Resumen
Primero, use un comando que funcione .
En segundo lugar, evite el almacenamiento innecesario en RAM y el procesamiento de datos potencialmente enormes.
La respuesta no especificó que la salida siempre es pequeña, por lo que también debe considerarse una posibilidad de salida grande.
fuente
[[ $(... | head -c | wc -c) -gt 0 ]]
o[[ -n $(... | head -c1) ]]
son mejores porquewc -c
tendrían que consumir toda la salida del comando.Esto ejecutará el comando y verificará si la salida (cadena) devuelta tiene una longitud cero. Es posible que desee consultar las páginas del manual de 'prueba' para otros indicadores.
Utilice el "" alrededor del argumento que se está comprobando, de lo contrario, los resultados vacíos generarán un error de sintaxis ya que no hay un segundo argumento (para verificar).
Nota: eso
ls -la
siempre regresa.
y,..
por lo tanto, usar eso no funcionará, consulte las páginas del manual de ls . Además, si bien esto puede parecer conveniente y fácil, supongo que se romperá fácilmente. ¡Escribir un pequeño script / aplicación que devuelve 0 o 1 dependiendo del resultado es mucho más confiable!fuente
$(
lugar de una cita inversa, porque$(
anida mejorPara aquellos que desean una solución elegante, independiente de la versión bash (de hecho, debería funcionar en otros proyectiles modernos) y para aquellos que adoran usar frases ingeniosas para tareas rápidas. ¡Aquí vamos!
(tenga en cuenta como uno de los comentarios mencionados,
ls -al
y de hecho, solo-l
y-a
todos devolverán algo, por lo que en mi respuesta utilizo simplels
fuente
grep -q ^
en su lugar, los caracteres de nueva línea también coincidirán, y grep no imprimirá nada en la salida estándar. Además, saldrá tan pronto como reciba cualquier entrada, en lugar de esperar a que finalice su flujo de entrada.ls -A
si desea incluir archivos de puntos (o directorios)Manual de referencia de Bash
6.4 Expresiones condicionales bash
Puedes usar la versión abreviada:
fuente
string
es sinónimo de-n string
.Como comentó Jon Lin,
ls -al
siempre saldrá (para.
y..
). Deseals -Al
evitar estos dos directorios.Podría, por ejemplo, poner la salida del comando en una variable de shell:
Una notación más antigua, no anidable, es
pero prefiero la notación anidable
$(
...)
Puedes probar si esa variable no está vacía
Y podrías combinar ambos como
if [ -n "$(ls -Al)" ]; then
fuente
Supongo que quieres la salida del
ls -al
comando, así que en bash, tendrías algo como:fuente
ls
nunca se ejecuta. Solo verifica si la expansión de la variableLS
no está vacía.-a
conmutador nunca devolverá ningún contenido (es decir, devolverá contenido si hay archivos o no) ya que siempre está presente lo implícito.
y los..
directorios.Aquí hay una solución para casos más extremos:
Esto funcionará
sin embargo,
fuente
Todas las respuestas dadas hasta ahora tratan con comandos que terminan y generan una cadena no vacía.
La mayoría están rotos en los siguientes sentidos:
yes
).Entonces, para solucionar todos estos problemas y responder la siguiente pregunta de manera eficiente,
puedes usar:
También puede agregar un tiempo de espera para probar si un comando genera una cadena no vacía dentro de un tiempo determinado, utilizando
read
la-t
opción 's . Por ejemplo, por un tiempo de espera de 2.5 segundos:Observación. Si cree que necesita determinar si un comando genera una cadena no vacía, es muy probable que tenga un problema XY.
fuente
seq 1 10000000
,seq 1 20
yprintf""
). El único enfrentamiento que este enfoque de lectura no ganó fue con el-z "$(command)"
enfoque de una entrada vacía. Incluso entonces, solo pierde alrededor del 10-15%. Parecen alcanzar el equilibrioseq 1 10
. En cualquier caso, el-z "$(command)"
enfoque se vuelve tan lento a medida que aumenta el tamaño de entrada que evitaría usarlo para cualquier entrada de tamaño variable.Aquí hay un enfoque alternativo que escribe el std-out y std-err de algún comando en un archivo temporal, y luego verifica si ese archivo está vacío. Una ventaja de este enfoque es que captura ambas salidas y no utiliza subcapas ni tuberías. Estos últimos aspectos son importantes porque pueden interferir con la captura del manejo de salida de bash (por ejemplo, aquí )
fuente
A veces desea guardar la salida, si no está vacía, para pasarla a otro comando. Si es así, podrías usar algo como
De esta manera, el
rm
comando no se bloqueará si la lista está vacía.fuente