Как стать автором
Обновить

Комментарии 52

В последнем скрипте допущена типичная ошибка — он неправильно обрабатывает директории с пробелом в имени.
На мой взгляд типичная ошибка это создавать директории с пробелами в имени.
И чего в этом плохого? Я всегда даю названия директориям в виде human readable. Уж programs to do some stuff сморится гораздо лучше prg_staff. Не в досе же живём, чессово.
Вот как раз programs to do some stuff смотрится фиговей чем programs_to_do_some_stuff. Причём речь даже не в скриптах: в обычной переписке выделить двойным кликом programs_to_do_some_stuff гораздо легче чем выделять programs to do some stuff и пытаться понять почему каталог programs to do не найден…
Может быть для этого нужны какие-то настройки, но у меня при этом выделяется тольок часть имени между подчёркиваниями ;)
это вы тем, кто выкладывает торренты расскажите :)
после отказа от виндовс(а в последствии и работы с ним по необходимости), заменил все пробелы на "_", это гораздо удобней при работе в консоли(на работе работаю 90% в ней, а отрывок скрипта, кстати имепнно с рабочего компа), tab`ом удобней пользоваться.
Какой-то у вас не правильный tab. Нормально он дополняет файлы с пробелами в имени.

Человек, утверждающий, что пробелы в имени не нужны, глубоко ошибается на мой взгляд.

Да, и еще, sudo не будет читать пароль из файла а попросит его с терминала. Попробуйте проверять утверждения, прежде чем публиковать статью — отсутствие документации порой лучше, чем ложная документация.
УЖОС:

LIST=`find /svn/ -type d 2>/dev/null| awk '{FS="/"} {print $4}'| sort|uniq | tr '\n' ' '`
for ONE_OF_LIST in $LIST
do
svnadmin hotcopy /svn/$ONE_OF_LIST /svn/temp4backup/$ONE_OF_LIST
done


$ echo "/1/2/3/4/5/6" | awk '{FS="/"} {print $4}'
почему-то ничего не выводит…

Если это linux, может быть лучше:
find /svn/ -mindepth 4 -maxdepth 4 -type d | while read ONE_OF_LIST; do
...
done
Вместо echo, лучше всегда использовать printf
И чем же printf всегда лучше чем echo? По ссылке написано «there are occasions where...»
Тем что printf соответсвует posix.
Очень просто: если printf иногда лучше echo и никогда не хуже (а так дела, собственно, и обстоят), то лучше забыть об echo…
к первому примеру можно рассказать про seq
Да. тоже об этом подумал. ЛУчше переделать первый пример так:

for i in `seq 0 4`

Ибо, если тебе надо, например, не 5 значений перебрать, а тысячи — не будешь же руками перечислять…
недавно пришлось писать скрипты на bash, и возникла ошибка с переносом строки. Хочу предупредить тех, кто будет создавать скрипты на bash из под FAR или из PSPad: перенос строки в dos и unix две РАЗНЫЕ вещи!

в PSPpad это лечится просто, Format->Unix (LF). В FAR`e не знаю.
Коммент конечно мой туп, но для новичком может стать крайне полезной информацией, особенно когда создаются файлы с символом переноса строки в конце имени ^M
писать под баш в фаре — это сильно))
в FAR'e Shift + F2
я обычно это лечу так:
в виме ":%s,\r,,g"
или можно прямо sed'ом
там где упоминается for i in 0 1 2 3 4, стоит добавить коментарий, что удобнее делать так:
for i in {0..4}
Для чистого sh, в freebsd можно использовать комманду jot(for item in `jot 50 1 50`), в линухе, к сожалению не помню.
В bash(как и многих других оболочках) есть встроенные файловые дескрипторы: 0 (stdin), 1 (stdin), 2 (stderr).


Опечатка — stdin 2 раза, а stdout отсутствует…
Опередили:)
Спасибо, исправил
Спасибо, особенно за «&», не знал и долго искал:)
Буду ждать продолжения.
И еще для более сложной и продвинутой математики можно использовать перенаправление на bc
спасибо,
надеюсь будете продолжать цикл статей про баш
просьба — не забывайте в статье вставлять ссылку на предыдущие части, так как некоторые моменты неплохо бы освежить, и нужно лезть искать…
хм… а я вроде бы вставлял.., ну да ладно :). Исправил.
Небольшая просьба тем, кто будет копировать статьи себе на сайт: Господа, ставьте ХОТЯ БЫ ссылку источник откуда берете. Уважайте себя и труд других.
простите, предыдущий коментарий был адресован всему топику, а не вам конкретно)
НЛО прилетело и опубликовало эту надпись здесь
Не думаю что такие маленькие кусочки кода сложно разобрать без подсветки. Однако, я приму ваше замечание.
НЛО прилетело и опубликовало эту надпись здесь
let "c = a / b" #умножение
Больше похоже на деление.

По умолчанию stderr не должен выводится в на консоль(писаться в stderr)
Мне кажется, что это неверно, да ещё и с опечаткой. stderr вроде как в консоль и пишется по умолчанию, но отдельно от stdout.

LIST=`find /svn/ -type d 2>/dev/null| awk '{FS="/"} {print $4}'| sort|uniq | tr '\n' ' '`
for ONE_OF_LIST in $LIST
do
...
done

Это, я думаю, более правильно делать как-то так:
find /svn/ -type d 2>/dev/null| awk '{FS="/"} {print $4}'| sort|uniq | while read ONE_OF_LIST
do
...
done


Вообще, статья оформлена несколько неряшливо. Спешили куда-то что ли?
Исправил ваши замечания. По поводу оформления, статья писалась обрывками 2,5 месяца, поэтому возможна некоторая разница в изложении материала + некоторые орфографические ошибки далеко не всеглда заметны(и чем больше перечитываешь статью, тем меньше они заметны). А по поводу примера, ну я это привел лишь как пример :), а так каждый сам решит как улчше это реализовать.
блин..., обещаю заняться постановкой синхронизации рук для печатания на клавиатуре :)
Еще немного иллюстраций

while :; do… done

myprogram <<< something_into_stdin
(см. раздел Here Strings, бывает удобно)

Это не запускайте!
:(){ :|:& };:
НЛО прилетело и опубликовало эту надпись здесь
Второй вариант.
Если баш — то второй вариант, хотя бы из-за того, что вложенность поддерживает.
Мои комментарии:
1) В примере с for — лучше вариант:
for i in {0..4}
или
for i in $(seq 0 4)
2) Часто использую бесконечный цикл:
while:; do чего-нибудь; done
(упс… узрел в комментах)
3) Арифметические действия:
echo $[2+2]
Полезность — вывести случайное число в диапазоне 1-100
echo $[ $RANDOM % 100 +1 ]
При необходимости использования дробей — команда bc:
(упс… узрел в комментах)
# echo 3/2 | bc -l
1.50000000000000000000
# echo $[3/2]
1
4) stdout и stderr в один файл:
./program_with_error >& file_with_out-and-err
5) Командная подстановка — кавычки ``:
удобнее пользоватся $() — так как удобнее можно делать вложения(без экранирования внутрених кавычек), например:
rm $(cat /tmp/list-$(whoami))
— удалит файлы по списку с имением /tmp/list-ИмяВыполневшегоКоманду
6) Про пробелы в именах файлов спорить не надо — скрипт нужно подстраивать под «сложные условия»:
лишний раз не ленится аргументы с использованием переменных в каваычки брать,
где можно у find, например, использовать опцию -print0, а у xargs — --null
А можно ли передать stderr на конвейер (pipe)?
НЛО прилетело и опубликовало эту надпись здесь
Смешается со stdout. Его можно закрыть:
foo 2>&1 >&- | bar
Помню, несколько лет (!) не мог писать полноценные баш скрипты, потому что про программу let не знал, а знал про expr.

А у этого expr есть особенность, о которой нигде толком не написано. А особенность в том, что на результат вычисления влияют пробелы.

#expr 1+3
1+3

#expr 1 + 3
4

Я писал выражения по первому варианту, и все никак не мог понять — как же делать математические вычисления? В доке написано, что вычисления возможны. На практике — возвращается исходная строка. В голове не укладывалось, что на результат могут влиять непечатные символы.

И вот только один раз скопипастив откуда-то скрипт, обнаружил, что в нем почему-то expr работает. Стал разбираться почему — чуть не свихнулся, думал уже, что какие-то переменные среды на результат влияют. Через пол-часа стало ясно почему. С новыми знаниями пересмотрел man expr — действительно, про правила форматирования математических выражений пробелами ни слова.
А всё потому, что не разучили вовремя, как шел передаёт аргументы :)
В отличии от ДОСа, например, где «cd\» сработает. Благодаря этому бремя парсинга выражения на expr не падает, делая его тривиальной программой — все аргументы раздельно переданы в ARGV().
А как вы узнали, что expr для нормальной работы нужно каждый элемент формулы как отдельный аргумент передавать? Вы выучили язык C, скачали исходники и разобрались, как там парсинг работает?

Я вот например думал, что такая прога, по нормальному-то, все аргументы должна в одну строку склеивать, а потом ее парсить. Конечно, если прогу вменяемый чел писал.
Да, я выучил язык C много лет назад, но это к делу не относится.
А к делу относится всего лишь man команды expr:

ARG1 | ARG2
              ARG1 if it is neither null nor 0, otherwise ARG2
ARG1 < ARG2
              ARG1 is less than ARG2
ARG1 <= ARG2
              ARG1 is less than or equal to ARG2
STRING : REGEXP
              anchored pattern match of REGEXP in STRING


Обратите внимание на пробелы вокруг операторов. Если бы их не было, неясно как бы он парсил, например, строчные аргументы, как в последнем случе с оператором «двоеточие».
> Обратите внимание на пробелы вокруг операторов.

Это я обратил внимание. Однако, в любом нормальном разгребателе выражений непечатные символы между токенами пропускаются, не такли? Это аксиома настолько стандартна, что отступая от нее, в документации об этом надо явно написать как минимум.

> Если бы их не было, неясно как бы он парсил, например, строчные аргументы, как в последнем случе с оператором «двоеточие».

А как бы он парсил строку с пробелами и двоеточиями вообще страшно подумать.
3й части нету? (

Спасибо за Ваши статьи! Жаль, что цикл прекратился. Остались не раскрытыми темы функций, массивов и подстановок.


Если кому-то интересно, о них можно узнать в простом самоучителе по программированию на Bash.

Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории