it-swarm-ru.tech

Как я могу назначить вывод команды для переменной Shell?

Я хочу присвоить результат выражения переменной и объединить его со строкой, а затем повторить его. Вот что у меня есть:

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

Но это выводит:

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

Итак, похоже, что это не назначается $thefile и ​​печатается по мере выполнения.

82
Nathan G.

Назначение оболочки - это одно слово без пробела после знака равенства. Итак, то, что вы написали, присваивает пустое значение thefile; кроме того, поскольку назначение сгруппировано с помощью команды, это делает thefile переменной среды, и назначение является локальным для этой конкретной команды, т. е. только вызов ls видит назначенное значение.

Вы хотите захватить вывод команды, поэтому вам нужно использовать подстановка команды :

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

(Некоторые литературные источники показывают альтернативный синтаксис _thefile=`ls …`_; синтаксис обратных кавычек эквивалентен синтаксису долларовых скобок, за исключением того, что кавычки внутри обратных кавычек иногда бывают странными, поэтому просто используйте $(…).)

Другие замечания о вашем сценарии:

  • Объединение _-t_ (сортировка по времени) с _-U_ (не сортировка) не имеет смысла; просто используйте _-t_.
  • Вместо того, чтобы использовать grep для сопоставления снимков экрана, проще передать подстановочный знак ls и ​​использовать head для захвата первого файла:

    _thefile=$(ls -t *"Screen Shot"* | head -n 1)
    _
  • Обычно это плохая идея разбирать вывод ls . Это может плохо работать, если у вас есть имена файлов с непечатными символами. Однако сортировать файлы по дате сложно без ls, поэтому это приемлемое решение, если вы знаете, что у вас не будет непечатных символов или обратной косой черты в именах файлов.

  • Всегда используйте двойные кавычки вокруг подстановки переменных , т.е. здесь пишите

    _echo "Most recent screenshot is: $thefile"
    _

    Без двойных кавычек значение переменной будет расширено, что вызовет проблемы, если оно содержит пробелы или другие специальные символы.

  • Вам не нужны точки с запятой в конце строки. Они избыточны, но безвредны.
  • В сценарии оболочки часто рекомендуется включать _set -e_ . Это говорит командной консоли завершить работу в случае сбоя какой-либо команды (возвращая ненулевой статус).

Если у вас есть GNU find (в частности, если вы работаете с не встроенным Linux или Cygwin), есть другой подход к поиску самого последнего файла: попросите find перечислить файлы и их даты, и используйте sort и ​​tail, чтобы извлечь самый младший файл.

_thefile=$(find -maxdepth 1 -type f -name "*Screen Shot*" -printf "%[email protected] %p" |
          sort -k 1n | tail -n 1)
_

Если вы хотите написать этот скрипт на zsh вместо bash, есть гораздо более простой способ перехватить новейший файл, потому что zsh имеет glob qualifiers , который разрешает подстановочные совпадения не только для имен, но и для файла. метаданные. Часть _(om[1])_ после шаблона - это квалификаторы glob; om сортирует совпадения по возрасту (т. е. по времени модификации, сначала самое новое), а _[1]_ извлекает только первое совпадение. Все совпадения должны быть в скобках, потому что технически это массив, так как глобализация возвращает список файлов, даже если _[1]_ означает, что в данном конкретном случае список содержит (максимум) один файл.

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

Если вы хотите сделать это с помощью нескольких строк/нескольких команд/с, то вы можете сделать это:

output=$( bash <<EOF
#multiline/multiple command/s
EOF
)

Или:

output=$(
#multiline/multiple command/s
)

Пример:

#!/bin/bash
output="$( bash <<EOF
echo first
echo second
echo third
EOF
)"
echo "$output"

Вывод:

first
second
third
4
Jahid