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

0

  1. 1
  2. 2
  3. 3
  4. 4
{  
   (cd "$DIR"; ls -1);
   {  xml2 < $XML | grep '/list/files/@path=' | cut -d = -f 2 | cut -d / -f 2 | sort | uniq; }   
} | sort | uniq --count | grep '^ *1' | awk '{print $2}' | (cd "$DIR"; xargs --no-run-if-empty rm -v)

Удаляет из "$DIR" всё, что не описано в files.xml.

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

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

  • > grep '/list/files/@path='
    xmllint --xpath не берет?
    > uniq --count | grep '^ *1' | awk '{print $2}'
    uniq -u же
    > xargs --no-run-if-empty rm -v
    лучше ./'{}' (а то мало ли, что в $XML

    зы... 2 cd - тоже не очень, и есть `combine' из `moreutils' (правда, хотя бы один из входов должен быть файлом), sort | uniq -> sort -u (и в данном случае можно без него)
    Ответить
    • > и есть `combine' из `moreutils'

      я подобные задачи - пересечение (предварительно отсортированых) множеств - приучился diff делать, который спокойно башевы `<(cmd)` конструкцие пережевывает и более портабельный. по выводу дифа можно грепнуть что есть только в левой части (^<), или что есть только в правой части (^>).

      и вместо `xargs` который по жизни кучу граблей портабельности имеет (например в hp-ux), я просто на лету sed'ом генерю комманды и потом их пайпю в шелл. типа: "ls -1 | sed 's!^!rm -rf !' | sh" - в особенности со встроеными коммандами это работает на ура.
      Ответить
      • > башевы `<(cmd)` конструкцие пережевывает и более портабельный

        Всё-таки s/и/или/. В 1 случае и `combine' поймёт `process substitution'.
        Во 2 сойдет `comm', разве что -123 не интуитивны, и для надёжного OR или XOR (только в одном) хуже подходит.

        > "ls -1 | sed 's!^!rm -rf !' | sh"
        "| sh" да на левом входе... "touch tilda". Лучше system(), посиксовый awk вроде поддерживает, или обернуть:
        | while read line; do ...; done
        
        alias wdo='while read l; do'		# для командной строки
        ls | wdo echo "$PWD/$l"; done		# silly full-path
        
        alias -g W='|while {read l;}'		# для zsh
        ls W {echo $l:A}			# silly full-path
        +Профит в виде чтения переменных, для awk же лучше явно передавать.

        > работает на ура
        Почему-то 😛 вспомнилось: http://bestbash.org/b_25471
        Ответить
        • >> башевы `<(cmd)` конструкцие пережевывает и более портабельный

          потому что баш стоит почти везде - в отличии от GNU *-tools/*utils

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

          > "| sh" да на левом входе... "touch tilda". Лучше system(), посиксовый awk вроде поддерживает, или обернуть:

          трюк с '| sh' позволяет (если сперва убрать '| sh') преварительно увидеть какие комманды будут исполнятся и их отдельно протестировать.
          другим образом протестировать комманды использующие </> редиректы почти невозможно.

          > +Профит в виде чтения переменных, для awk же лучше явно передавать.

          да, да. но. как по мне почти все что `while read` может делать, можно сделать и без него. я стараюсь почти для всего найти вариант с пайпами что бы туда еще можно было и xargs всобачить. например удаление файлов по одиночке будет подтормаживать на больших количествах - с xargs'ом для групировки файлов заметно быстрее. и xargs совместим с '| sh' трюком 🙂

          например, сравни это:
          ls | while read l; do rm "$PWD/$l"; done

          с вот этим:
          ls | xargs -n 100 | sed 's!^!rm !' | sh


          пайплайнинг и паралелизация в полный рост. 😉
          Ответить
          • Привел же пример, вот еще один: touch "$'\x2f'star&echo применяется патч Бармина, ^C - покаяться"
            Ответить
          • > еще можно было и xargs всобачить
            Вы сидели на стуле "портабельность", что несколько ослабляет аргумент.

            > например удаление файлов по одиночке
            Именно в этом случае `find .. -delete'.

            > xargs совместим с '| sh'
            Не всегда хаrgs критичен (есть и find +), имхо, это того не стоит.
            Ответить
            • > > еще можно было и xargs всобачить
              > Вы сидели на стуле "портабельность", что несколько ослабляет аргумент.

              `xargs -n NNN` - это тоже POSIX.

              использование подстановки типа '-I {}' - которое тоже к слову POSIX - по моему опыту минное поле. потому что куча find'ов не правильно обрабатывает `-I` параметр если нужно вместо '{}' какую другую строку использовать.

              > этц про find, включая +

              насчет `+` мой первый же тест (минуту назад (-: ) показал проблему:
              "find: echo: Argument list too long". другими словами это неправильная замена xargs, т.к. xargs он в обе стороны работает: с одной стороны он агрегирует много строк в меньшее количество строк, с другой стороны он регулирует длину комманды что бы она за лимит не выходила.
              Ответить
              • > что куча find'ов не правильно обрабатывает `-I` параметр если нужно вместо '{}' какую другую строку использовать.

                find и -I не очень понял, можно пример? Об этом ограничении: plus sign that follows an argument containing the two characters "{}" (всмысле аргумент должен быть последним).

                > find: echo: Argument list too long
                Не воспроизводится. Судя по ману и проверке тоже вызавает несколько раз. Но буду иметь ввиду.
                Ответить
                • > find и -I не очень понял, можно пример?

                  оопс. это я стормозил и попутал с совсем не той проблемой. `-I` это у xargs, а не find. и эта проблема тут ни причем.

                  ЗЫ xargs на некоторых платформах если указать `-I` параметр перестают подставлять имена файлов вообще и просто комманду буквально как написано выполняют.

                  > > find: echo: Argument list too long
                  > Не воспроизводится

                  это у тебя в каталоге мало файлов. напусти чего-нибудь такое:
                  for X in `seq 1 10000`; do echo  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$X; done

                  и попробуй еще раз, например с "find $PWD" а не просто "find ."

                  фишка `find -exec +` что он запускает команду один раз на весь подкаталог. если в каталоге слишком много файлов, то длина команды легко переваливает за лимит (в общем случае 32К) и команда не выполняется.
                  Ответить
                  • Какой-то неправильный у вас find.

                    $ for X in `seq 1 10000`; do touch aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$X; done
                    $ echo * | wc
                          1   10000  458894
                    $ find | wc
                      10001   10001  478896
                    $ find -exec echo '{}' + | wc
                          4   10001  478896

                    Из последней команды видно, что echo выполнилось 4 раза.
                    Ответить
                    • > Какой-то неправильный у вас find.

                      не уверен. глянь в свой /usr/include/limits.h и посмотри чему равно ARG_MAX. (на линухе - сразу в /usr/include/linux/limits.h)

                      > $ echo * | wc

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

                      > $ find -exec echo '{}' + | wc

                      если запустить на моем линухе `find -exec echo '{}' + >/dev/null` первые три строки выглядят так:
                      find: echo: Argument list too long
                      find: echo: Argument list too long
                      find: echo: Argument list too long
                      и wc показывает неправильные цифры.

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

                      самый прикол что на моем SLES 10.2 ARG_MAX самый маленький - 128K. на 10й солярке 2MБ. на AIX официально 24К, но я не вижу что бы этот лимит какой-то роли играл. HP-UX - 1MB.

                      у тебя на системе ARG_MAX стоит в минимум 512К

                      вообщем разброд и шатание, ну да я уже привык это ограничение обходить.
                      Ответить
                      • Там ключевое было: > Из последней команды видно, что echo выполнилось 4 раза.

                        У меня было так (лимит вроде 128k):
                        /bin/echo /media/*/*/*/*/*/*
                        bash: /bin/echo: Argument list too long
                        find /media -maxdepth 6 -mindepth 6 -exec echo '{}' +
                        выводит
                        Ответить
                      • ARG_MAX у меня равен 131072 — как раз чтобы разбить 458894 байт на 4 строки.

                        А find у вас какой-то кривой.
                        $ find --version | head -1
                        find (GNU findutils) 4.4.2
                        $ `which echo` --version | head -1
                        echo (GNU coreutils) 7.4
                        Ответить
                      • Впрочем, здесь не в ARG_MAX дело. Какой у вас ulimit -s? Проблемы начнутся около 512.
                        Ответить
                        • в это ARG_MAX и есть проблема.

                          размер стека (главного потока) как правило большой (и у меня 8МБ) что бы его так легко переполнить.

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

                          да и если процесс стек переполнит, то он будет просто убит каким SEGV. красивых сообщениях об ошибках ты не увидишь.
                          Ответить
                          • Преблема, если ARG_MAX больше четверти лимита стека. find, очевидно, режет на строки по ARG_MAX, а реальный лимит — четверть стекового (не думаю, что у вас версия меньше 2.6.23).
                            Ответить
      • Нафига diff, когда есть каноничный посиксовый join?
        Ответить
    • xml2 просто удобная штука, как poor man's xpath: смотришь что она выводит и без справочников сразу знаешь что тебе нужно. Есть ещё 2xml, html2, 2html.
      Ответить
  • О, давно я половыми извращениями не страдал. Надо будет попарсить XML на gawk'е.
    Ответить
      • Неправда. GAWK можно использовать не только для того, чтобы вывести третью колонку данных и передать её дальше в греп.
        Бывший босс делал какую-то свою хитрую систему, ему там было нужно сделать nslookup множества доменов, получение уникальных строк и засовывание айпишников в файервол. Я небольшой кусочек помог, но там вышел какой-то дикий скрипт на баше. Ради интереса посидел два часа, переписал полностью на gawk. Офигенная штука, скажу я. И с текстами работать умеет. И как-то там парсить. Самое то.
        Ответить
  • о(X"F.D(YM$W!YN.H.H)G(A(L$V$Z E,WH!B.Q.O$G?T?G(M,TC N?A.Y.J!N D:G,A,BZ$A KL:C:E$J$MR,T)K?IH.O"P.J,Q,L"M"H.W:I$J$I,V.C!N.R:J?L)E"O)R!W!P O$D,S:V"I?L"EI$I?J"J$U.B(J)G H?A!E Q,HM!P,S"K?D!D!RW(A J!BR:S)X?D!RS)IS:K,T?Q.X,K(S!MR(KYF!S)R S:J?H$CD:O.S:O.ZX.L,X!W"M?N"X?V!T,I!E)Q.F"V$QL.C M,Z?M)T:A R)S!E!B!E H.K,DP N$O?Q:D(K H:Q!J D.N)E VU,W)Q,V,D!X)G:O?LMI?W,V.K)S C:P$U"V:N)W?K?K(P:G)T,M Y$SF?F?D:W.S?C:K,L)Z!M)G?X)O(J,M(M D:W!KY(M.G$S O:X:GT$L:A(U(G:Z)J?A(A:A?P!AS$W$J!L(A B.C$DF)O.I.M:B!P!C)R$I.R.I?Z.Q"RO"K$U E(C)X?D?B$B)H(F!J"M!P$L$E!X:M,X?Y:O)F"Y$H)I?XO:T?O(J,U!E!T G"Q?O"I.E?P"T Y)U)X?I!G?M!F:H)I!D:SP)X?P?E(Q:E,W,L:A(B X$X:Y.J!Q!I$U)I?X?K(M(D(C$E,M$KZN,O.O!A Z"P R.V K.B D A XU:O(NJ:I"Z?F)Z?K.AV D)Q)V"V)R.S(G.B$A,L$DD(J(M!N)D)S,OH!HI"W,M$L.J:A,O:S?J?G,J Q(O N(Y,F(F)H"Q,T.D(B?U!Y P!A(I!N.O)W$A$C?U)Y:E I$I?G!A!I?T?G?V T!Z:X$B!R$L:I$P(K"G.E(L)JZ?V S"M$H$B(P$O I:C?W(P$V!E(G X?Q$C!I:P Q$M,K$L,Y?L!S!L!LS!P.J)G,C.GY.Y?V(R(M?W:T?E)O)H)I(K:K"M?X"Z$I?C!J.A)X:L"T(S$H(P?F!V$R,TU,I,V:H(LM!H$G$X)R FL)V!J:W,QN:S)Y:O)N:P$R.K.R:T!S"T:G(K.W(PE!Q.K"I R"J TX Y!K$X.V$RM"N.I(PUZ.C$N.X V E(G E(S(KPN:L(W?F(N$P)T)L!O.W?R,P"B?L.X!U M:T,B?XH"G!V G.PA)E(T(VI,B:I$N.D:A(Y)H(Z!I$I!K,K!KL(O(Z)S$J)I$Z$W(G"A)S!CT B:E Y$C!DHJ$S:Q G$T.J?J,E:D:HJ,K"SKT.B P Q?V"A!L!S:X,H,C$W!W!H.C!X?Y!FC$I?T!X(M,N!W)A?Y?L"XX U(P,O.D(O,O:H.Y"Q:R.D J:J,D(E:B?Z.J W!G!A:J,A!W!Y,VQ?C!JСTADPORHJQXRIYUZAUSUSJPUM
    Ответить

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

Где здесь C++, guest?!

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


    8