bash – ¿Cómo puedo asignar la salida de un comando a una variable de shell?

Pregunta:

Quiero asignar el resultado de una expresión (es decir, la salida de un comando) a una variable y luego manipularla; por ejemplo, concatenarla con una cadena y luego repetirla. Esto es lo que tengo:

#!/bin/bash
cd ~/Desktop;
thefile= ls -t -U | grep -m 1 "Screen Shot";
echo "Most recent screenshot is: "$thefile;

Pero eso da como resultado:

Screen Shot 2011-07-03 at 1.55.43 PM.png
Most recent screenshot is: 

Entonces, parece que eso no se está asignando a $thefile y se está imprimiendo mientras se ejecuta.

¿Qué me estoy perdiendo?

Respuesta:

Una asignación de shell es una sola palabra, sin espacios después del signo igual. Entonces, lo que escribió asigna un valor vacío al thefile ; además, dado que la asignación está agrupada con un comando, convierte el thefile una variable de entorno y la asignación es local para ese comando en particular, es decir, solo la llamada a ls ve el valor asignado.

Desea capturar la salida de un comando, por lo que debe usar la sustitución de comandos :

thefile=$(ls -t -U | grep -m 1 "Screen Shot")

(Alguna literatura muestra una sintaxis alternativa thefile=`ls …` ; la sintaxis de las comillas inversas es equivalente a la sintaxis de los paréntesis de dólar, excepto que las comillas interiores entre comillas son raras a veces, así que use $(…) .

Otras observaciones sobre su guión:

  • Combinar -t (ordenar por tiempo) con -U (no ordenar con GNU ls ) no tiene sentido; solo usa -t .

  • En lugar de usar grep para hacer coincidir las capturas de pantalla, es más claro pasar un comodín a ls y usar head para capturar el primer archivo:

     thefile=$(ls -td -- *"Screen Shot"* | head -n 1)
  • Generalmente es una mala idea analizar la salida de ls . Esto podría fallar bastante si tiene nombres de archivo con caracteres no imprimibles. Sin embargo, ordenar los archivos por fecha es difícil sin ls , por lo que es una solución aceptable si sabe que no tendrá caracteres no imprimibles o barras invertidas en los nombres de los archivos.

  • Utilice siempre comillas dobles en las sustituciones de variables , es decir, escriba aquí

     echo "Most recent screenshot is: $thefile"

    Sin comillas dobles, el valor de la variable se vuelve a expandir, lo que causará problemas si contiene espacios en blanco u otros caracteres especiales.

  • No necesita punto y coma al final de una línea. Son redundantes pero inofensivos.

  • En un script de shell, a menudo es una buena idea incluir set -e . Esto le dice al shell que salga si falla algún comando (devolviendo un estado distinto de cero).

Si tiene GNU find y sort (en particular si está ejecutando Linux no integrado o Cygwin), hay otro enfoque para encontrar el archivo más reciente: find lista de archivos y sus fechas, y use sort y read (aquí asumiendo bash o zsh para -d '' para leer un registro delimitado por NUL) para extraer el archivo más reciente.

IFS=/ read -rd '' ignored thefile < <(
  find -maxdepth 1 -type f -name "*Screen Shot*" -printf "%T@/%p\0" |
    sort -rnz)

Si está dispuesto a escribir este script en zsh en lugar de bash, hay una manera mucho más fácil de capturar el archivo más nuevo, porque zsh tiene calificadores glob que permiten coincidencias de comodines no solo en nombres sino también en metadatos de archivos. La parte (om[1]) después del patrón son los calificadores glob; om ordena las coincidencias aumentando la edad (es decir, por hora de modificación, la más reciente primero) y [1] extrae solo la primera coincidencia. Toda la coincidencia debe estar entre paréntesis porque técnicamente es una matriz, ya que globbing devuelve una lista de archivos, incluso si [1] significa que en este caso particular la lista contiene (como máximo) un archivo.

#!/bin/zsh
set -e
cd ~/Desktop
thefile=(*"Screen Shot"*(om[1]))
print -r "Most recent screenshot is: $thefile"

Leave a Comment

Your email address will not be published.

Scroll to Top

istanbul avukat

-

web tasarım