LINUX.ORG.RU

Что не так в этом BASH? В упор не вижу ошибки

 , ,


0

2

Предыстория

Случается такое - вроде всё нормально и хорошо, но не работает. Смотришь еще раз - аналогично. Сейчас у меня как раз такой случай.

Задача

Есть аудиофайлы. Ради неизвестно чего мне захотелось посмотреть waveform в подробностях (а файлов немало), и audacity для сего не очень оказался удобным и производительным. Решение - ffmpeg и gnuplot. Подготовим gnuplot к работе:

% cat ~/waveform.gnuplot
set terminal png transparent truecolor size 10000,1000;
set output ;

  unset key;
  unset tics;
  unset border;
  set lmargin 0;
  set rmargin 0;
  set tmargin 0;
  set bmargin 0;

  plot '<cat' binary filetype=bin format='%int16' endian=little array=1:0 with lines;
Проверяем наличие данных:
% cd ~/tests
% ls -1
A Return To The Sea (bonus track).flac
Angels Fall First.flac
alltoplot
Содержание скрипта:
% cat alltoplot
#!/usr/local/bin/bash
ls -1 | grep .flac | while read a; do
ffmpeg -i "$a" -ac 1 -filter:a aresample=11025 -map 0:a -c:a pcm_s16le -f data - | gnuplot ~/waveform.gnuplot | dd of="$a".png
echo "$a"
done
Краткое объяснение скрипта - построчно читаем вывод «ls -1 | grep .flac». Используем в качестве аргументов для ffmpeg и dd. И так пока не закончатся строки. В качестве debug-a добавил echo «$a»

Что мы имеем в результате? А вот что. http://paste.ubuntu.com/10505481/
Для ленивых !Ъ: во второй итерации по неведомой причине пропадает несколько первых символов в переменной $a, что приводит к «all First.flac: No such file or directory».

Дополнительная информация

1) Не смущайтесь от #!/usr/local/bin/bash - это норма
2) bash самой последней версии. Хотя это ничего не изменило
3) FreeBSD ни при чем. Тестировал в linux предварительно поправив скрипт - поведение аналогичное, только символов съедает немного больше.
4) если убрать строку с «ffmpeg ...», то echo «$a» выдает правильные значения.

★★★★★
Ответ на: комментарий от anonymous

Мм. очевидно же вроде, нет?
Или намек на то, что применение PIPE в скрипте может «подхватить» что-то из «read a;»?

reprimand ★★★★★
() автор топика
Ответ на: комментарий от anonymous

#!/usr/local/bin/bash

тему не читай&сразу отвечай

ls -1 | grep .flac

если ты о grep .flac - то это временное решение

reprimand ★★★★★
() автор топика

Цикл норкоманский.
Юзай
for i in *.flac

Тред не читал

zolden ★★★★★
()
Ответ на: комментарий от reprimand

а если так?

#!/bin/bash

touch stdin
seq 10 | while read a; do
  (
  read b
  echo "$a"
  ) <stdin
done

Цикл норкоманский.

то ли ещё будет

anonymous
()
Ответ на: комментарий от reprimand

тему не читай&сразу отвечай

man env, убогий.

если ты о grep .flac - то это временное решение

...а также help for.

anonymous
()

Да...
Видимо, пришло время мои скудные знания bash расширить, ибо в текущем положении дел мне остается овечать только ЯННП.
Спасибо анонимам и регистранту за ответы, пойду что-ли матчасть смотреть.

reprimand ★★★★★
() автор топика
Ответ на: комментарий от reprimand

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

xaizek ★★★★★
()
Последнее исправление: xaizek (всего исправлений: 1)

Ты пережимаешь в пцм? А проверил что там сырые фреймы? Точно? Ибо первые 44 байта - заголовок вафки, который кстати записывается в файл (если в файл, конечно) только ПОСЛЕ генерации всех фреймов, т.к. заранее их число может быть не известно. Так вот может ффмпег пытается в стдин впилить «в прошлое» эт самый заголовок, когда файл заканчивает. Ну и там конечно бинарщина в этих 44 байтах, она тебе походу и портит картину.

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

Ты пережимаешь в пцм? А проверил что там сырые фреймы? Точно? Ибо первые 44 байта - заголовок вафки, который кстати записывается в файл (если в файл, конечно) только ПОСЛЕ генерации всех фреймов, т.к. заранее их число может быть не известно. Так вот может ффмпег пытается в стдин впилить «в прошлое» эт самый заголовок, когда файл заканчивает. Ну и там конечно бинарщина в этих 44 байтах, она тебе походу и портит картину.

я работал с строкой без скрипта. Всё отлично работает. Там сырые фреймы, потому что я указал -f data. Изображение на выходе получается, притом неплохое.

Вся проблема в том, что баш я изучал «нахрапом» и совершенно несистемно. Сейчас мне нужно решить таск (ибо этот скрипт - часть отдельного проекта), но это сделать не получается. Вот и приходится «начинать» учить bash как следует. В теме же намеки.

reprimand ★★★★★
() автор топика
Последнее исправление: reprimand (всего исправлений: 1)
Ответ на: комментарий от deep-purple

да. Работает. И поэтапно и однострочником тоже работает.
Суть в том, что файлов МНОГО. И я не хочу каждый раз вручуню вписывать аргументы для -i и для выходного файла.

reprimand ★★★★★
() автор топика
Ответ на: комментарий от deep-purple

когда будешь пробовать, есть вероятность, что тебе надо будет заменить "-f data" на "-f nut"

reprimand ★★★★★
() автор топика
Последнее исправление: reprimand (всего исправлений: 1)

короче забил я на эти велосипеды и использовал for
текущий task решен, но чувствую я, что упускаю что-то

reprimand ★★★★★
() автор топика
Ответ на: комментарий от reprimand

Ня:

#!/bin/sh
find . -name '*.mp3' -exec sh -c 'ffmpeg -i "$0" -ac 1 -ar 11025 -f s16le -acodec pcm_s16le - | gnuplot ./gplt | dd of="$0".png' {} \;

deep-purple ★★★★★
()
Ответ на: комментарий от reprimand

но чувствую я, что упускаю что-то

for тебе сломает файлы с пробелами, а потом ещё есть ограничение на размер вводимых данных. Лучше уж пайпом в while.

Darth_Revan ★★★★★
()
Ответ на: комментарий от Darth_Revan

for тебе сломает файлы с пробелами

Ловите наркомана.

AnDoR ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.