Хотите проверить, была ли команда выполнена успешно, перенаправив ее вывод в переменную - PullRequest
23 голосов
/ 18 апреля 2011

В настоящее время я пишу сценарий bash, который загружает видеофайлы на YouTube, используя GoogleCL .

Поскольку я делаю эту загрузку в цикле (поскольку может быть несколько видеофайлов), я хотел бы проверить, был ли каждый файл загружен успешно, прежде чем загружать следующий.

Команда google youtube post --access unlisted --category Tech $f (где $ f представляет файл) выводит строку, которая сообщает мне, была ли загрузка успешной или нет.

Но я не знаю, как перенаправить эту «возвращаемую строку» в переменную, чтобы проверить успешность.

Вот что у меня есть:

for f in ./*.ogv ./*.mov ./*.mp4
do
    if [[ '*' != ${f:2:1} ]]
    then
        echo "Uploading video file $f"

        # How to put the return value of the following command into a variable?
        google youtube post --access unlisted --category Tech $f > /dev/null

        # Now I assume that the output of the command above is available in the variable RETURNVALUE
        if [[ $RETURNVALUE == *uploaded* ]]
        then
            echo "Upload successful."
        else
            echo "Upload failed."
        fi
    fi
done

Кто-нибудь может мне помочь?

Ответы [ 7 ]

21 голосов
/ 18 апреля 2011

Я предполагаю, что вы также можете зависеть от кода ошибки из команды Google (я предполагаю, что он возвращает ошибку, если не удалось загрузить, но вам, вероятно, следует проверить это дважды).

for f in ./*.ogv ./*.mov ./*.mp4; do
  if [[ '*' != ${f:2:1} ]]; then

    echo "Uploading video file $f"
    if google youtube post --access unlisted --category Tech "$f" > /dev/null
    then
      echo "Upload successful."
    else
      echo "Upload failed."
    fi

  fi
done

Распространенным заблуждением является то, что если требуется вычислить выражение в скобках, это не так, если всегда принимает команду и проверяет состояние ошибки;обычно это команда [, которая является псевдонимом для test, который оценивает выражение.(И да, я был бы удивлен, если бы не было оптимизированного ярлыка для ускорения его работы в bash, но концептуально это все еще верно).

Захват вывода осуществляется с помощью обратных галочек, например

result=`command argument a b c`

или с использованием $()

result=$(command argument a b c)

, но в этом случае, вероятно, лучше использовать код ошибки.

РЕДАКТИРОВАТЬ: У вас естьЗабавно, если что-то есть в вашей функции. Сначала я этого не заметил, но этого можно избежать, если вы включите опцию оболочки nullglob (из-за этого ./*.mov расширится до пустой строки, если файлов нет).Кроме того, заключите в кавычки, что $f или он сломается, если ваши имена файлов будут содержать пробелы

shopt -s nullglob
for f in ./*.ogv ./*.mov ./*.mp4; do
  echo "Uploading video file $f"
  if google youtube post --access unlisted --category Tech "$f" > /dev/null
  then
    echo "Upload successful."
  else
    echo "Upload failed."
  fi
done

HTH.

4 голосов
/ 18 апреля 2011

Я бы назвал это, The command ... outputs a string.' Return ' - это ключевое слово, а возвращаемое значение - это число, где 0 означает успешное соглашение (0 ошибок), а другое значение указывает код ошибки.

Вы получаете выводпо:

result=$(google youtube post --access unlisted --category Tech $f)

, но часто будет видеть низшее решение:

result=`cmd param1 param2`

низшее, потому что обратные метки легко путать с апострофами (в зависимости от шрифта) и трудно вкладывать, поэтомуне используйте их.

Из 'man bash':

Возвращаемое значение простой команды - ее состояние выхода, или 128 + n, если команда завершается сигналом n.

и:

return [n]
Вызывает выход из функции с возвращаемым значением, указанным в n.Если n опущено, возвращается статус последней команды, выполненной в теле функции.Если используется вне функции, но во время выполнения скрипта с помощью.(исходная) команда заставляет оболочку прекратить выполнение этого сценария и возвращает либо n, либо состояние завершения последней команды, выполненной в сценарии, в качестве состояния выхода сценария.Если используется вне функции, а не во время выполнения сценария., Возвращаемый статус - false.Любая команда, связанная с ловушкой RETURN, выполняется до возобновления выполнения после выполнения функции или сценария.

Код возврата / выхода последней команды получается через $ ?.

Ключевое слово, которое вы имели в виду, это подстановка команд .Снова 'man bash':

Подстановка команд
Подстановка команд позволяет выводу команды заменить имя команды.Существует две формы:

          $(command)
   or
          `command`

Bash выполняет раскрытие, выполняя команду и заменяя подстановку команды стандартным выводом команды, с удалением всех завершающих строк новой строки.Внедренные новые строки не удаляются, но они могут быть удалены во время разделения слов.Подстановка команд $ (cat file) может быть заменена эквивалентной, но более быстрой $ (

   When  the old-style backquote form of substitution is used,

обратный слеш сохраняет свое буквальное значение, за исключением случаев, когда за ним следует $, `или.Первая обратная кавычка, которой не предшествует обратная косая черта, завершает подстановку команды.При использовании формы $ (команда) все символы в скобках составляют команду;ни один из них не обрабатывается специально.

   Command substitutions may be nested.  To nest when using the

Форма с обратными кавычками, экранируйте внутренние обратные кавычки с обратными слешами.

Если подстановка встречается в двойных кавычках, разделение слов и расширение имени пути не выполняются.

2 голосов
/ 18 апреля 2011

Если вы все еще получаете вывод после > /dev/null, тогда он выводится на stderr, поэтому стандартные обратные пометки или $() не будут работать.

Во-первых, посмотрите, не указывает ли код возврата проблему: Проверьте $? после успеха и неудачи.

Если оказывается, что кода возврата недостаточно, вы можете перенаправить вывод:

RETURNVALUE=$(google youtube post --access unlisted --category Tech $f 2>&1 >/dev/null)

2>&1 помещает stderr в стандартный вывод stdout, прежде чем перенаправить стандартный вывод в ничто.

2 голосов
/ 18 апреля 2011

Использование $()

variable=$(google youtube post --access unlisted --category Tech $f )
0 голосов
/ 02 марта 2013

Ответ на вопрос заключается в использовании команды read.

Конечно, все эти другие ответы показывают способы не делать то, что попросил ОП, но это действительно мешает остальным, кто искалвопрос ОП.

Отказ от ответственности: Это дублирующий ответ

Вот как вы это делаете ...

Команда:

# I would usually do this on one line, but for readability...
series | of | commands \
| \
(
  read string;
  mystic_command --opt "$string" /path/to/file
) \
| \
handle_mystified_file

Вот что он делает и почему это важно:

  1. Давайте представим, что series | of | commands - это очень сложная серия переданных команд.
  2. mystic_command is может принять stdin в качестве файла, но не параметр arg , поэтому он должен входить в качестве переменной **
  3. read принимает stdin и размещает егов переменную $string
  4. Помещать read и mystic_command в «подоболочку» через круглые скобки не нужно, но она превращается в непрерывную трубу, как будто две команды находятся в отдельномфайл сценария.

** Всегда есть альтернатива, и в этом случаеальтернатива уродлива и нечитаема:

mystic_command --opt "$(series | of | commands)" /path/to/file | handle_mystified_file
0 голосов
/ 01 ноября 2011

Пример для доступа к youtube

rm ~/temp/youtube_top_title1.txt
rm ~/temp/youtube_top1.txt
curl  "http://www.youtube.com/"|\
grep -o 'watch[^"]*'|\
sort -n|\
uniq -c|\
awk '{if ($1!="1") print $2}'|\
while read i ; do\
    page_youtube=`curl -s  "http://www.youtube.com/${i}"`;\
    echo `echo -e "$page_youtube" |awk '{if ($1 ~ "") start=1; if ($1 ~ "") start=0; if (start == 1) print $0 }'|grep -v ''` >> ~/temp/youtube_top_title1.txt
    url_current=$(echo -e "$page_youtube"|\
    grep -o "url=[^,]*,"|\
    sed 's/url=//g;s/,//g'|\
    php -r '$f=fopen("php://stdin","r");while (FALSE!==($line=fgets($f))) echo urldecode($line);'|\
    awk '{print $1}'|\
    sed 's/;$//g'|\
    sed 's/\\u.*//g'|\
    tail -2|\
    head -1)
    echo "$url_current" >> ~/temp/youtube_top1.txt
done 
0 голосов
/ 18 апреля 2011

Вы можете присвоить его переменной с помощью обратных галочек:

CONTENT=`google youtube post --access unlisted --category Tech $f > /dev/null`
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...