image

Всем привет!

После вчерашнего поста о замене штатного ls другими штатными (или не очень) утилитами, я просто не мог пройти мимо комментов, особенно учитывая то что пост взлетел на вершины хит-парадов и за сутки его прочитало 18k, с хвостиком человек. Хабровчане подарили миру много новых способов избавиться от ls. Я их все (но это не точно) проверил, некоторые «причесал», что бы они соответствовали условиям задачи, и хочу поделиться с вами. Наслаждайтесь!

1. dir


Да, чОрт возьми. У меня она совершенно вылетела из головы. И хотя она совсем другая чем в DOS, Windows и даже в OS/2, свои функции выполняет исправно!
Про неё мне напомнили eumorozov и cru5ader

dir -aA ~

2. printf


Каюсь. zsh меня испортил и я считал, что print это такая утилита — лайт версия echo, а оказалось что это просто потроха самого zsh. Зато iig показал мастер-класс использования printf

printf "%s\n" ~/* ~/.*

3. echo


Да, это снова он… работающий через автоматический autocompletion. За такое благодарим SlavniyTeo

echo -e 'echo \t\ty\b\b\b\b\b\b\b' | bash -i
echo -e 'echo \t\ty\b\b\b\b\b\b\b' | sh -i

А вот пользователям zsh не повезло, хотя может быть если настроить?

3. vim


cru5ader напомнил, что в vim есть собственный файловый браузер, а так как vim есть везде (ну почти. На манджаро стоит обычный vi и с ним такой фокус не пройдёт) то почему бы этим не воспользоваться?

vim ~

4. rm


Да! Ваши глаза вас не обманывают. То что является основой знаменитого патча Бармина, которым пугают начинающих юниксоидов, мы будем использовать исключительно в мирных целях. Спасибо POPSuL

yes "n" | rm -i $HOME/* $HOME/.* 2>&1|grep -o "$HOME[^']*"

И Cheater

(echo y; yes n) | rm -ir ~ 2>&1 | sed -E -e "s/(rm:[^']+)|\?//g"

5. rsync


А собственно, почему-бы и не да? Благодарим за это 027

rsync --list-only ~/

6. grep


Грепом можно не только проверять e-mail на валидность, но и выгреПать файлы. kashtan404 и
KorDen32 показали что и это ему под силу (пофикшено на более правильный вариант).

grep -l '.*' ~/* ~/.* 2>/dev/null || grep -L '.*' ~/* ~/.* 2>/dev/null

7. file


Хотите понять что за файлы лежат в вашем хомяке? А может просто вывести их список? 027 и POPSuL доказали что и это ему под силу.

file ~/* ~/.*

8. stat


Статус файла или целой файловой системы? Не только! Способов нетрадиционного приготовления stat существует как минимум три. Одно даже от меня.

stat ~/* ~/.*|grep "/home"|awk '{print $2}'

Другое от polar_yogi

stat -c "%A %G:%U %s %x %n" * \.*

И третье от iig

stat *|awk '/File:/{print $2}'

9. head


Artyushov — голова! Показал как надо использовать head!

head -n 0 -v ~/* ~/.*|awk '{print $2}'

10. getfacl


Ключевая буква в названии этой утилиты — «f» и Zoro это доказал!

getfacl ~/* ~/.* | grep "# file" | awk '{print $3}'

11. git


Да, даже Git камрад tork заставил работать на хомяка!

git init ~/ ; curr=`pwd`; cd ~ ; git status; rm -rf .git; cd $curr ; curr=''

12. cat


Все любят котиков. Но самые крутые у пользователей BSD систем! К сожалению в линуксе котики не той породы. :-( Uzix похвастался своим cat-ом.

cat ~ |strings |xargs -IX sh -c 'test -e X && echo X'

13. lsattr


lsattr это не только ценный мех смотрелка аттрибутов файлов, но и смотрелка списка самих файлов. Neveil показал как это сделать.

lsattr ~/* ~/.* 2>&1 | grep -Po '/.*'

Эпилог


На чёртовой дюжине я пожалуй остановлюсь, но интересующиеся могут заглянуть в комменты оригинального поста и насладиться, так как «за бортом» остались однострочники на perl, ruby, python, php и даже С++.

Комментарии (50)


  1. 027
    12.09.2019 11:28

    git init ~/; git status

    Я там поправочку вносил, чтобы мусора не оставалось:
    git init ~/ ; git status; rm -rf .git


    1. Oxyd Автор
      12.09.2019 11:38

      Поправил и добавил.


      1. 027
        12.09.2019 11:54
        +1

        Это да, я бездумно добавил из исходного примера с просмотром текущей директории.
        А вот так попроще будет:

        git init ~/ ; cd ~ ; git status; rm -rf .git; cd -

        Кстати, будет досадно, если в исследуемом каталоге .git уже был. :)


        1. miraage
          13.09.2019 00:47

          Можно завернуть в subshell, чтобы cd обратно не делать.


          1. 027
            13.09.2019 19:59

            Кстати, да, я вечно про него забываю.


        1. Oxyd Автор
          13.09.2019 04:02

          Всё хорошо с Git, кроме одного косяка…
          "\320\224\320\276\320\272\321\203\320\274\320\265\320\275\321\202\321\213/"
          "\320\227\320\260\320\263\321\200\321\203\320\267\320\272\320\270/"
          "\320\230\320\267\320\276\320\261\321\200\320\260\320\266\320\265\320\275\320\270\321\217/"
          "\320\234\321\203\320\267\321\213\320\272\320\260/"
          "\320\240\320\260\320\261\320\276\321\207\320\270\320\271 \321\201\321\202\320\276\320\273/"

          Это собственно каталоги с русскими именами. Шаблоны, Рабочий стол, вот это вот всё. ;-)


          1. 027
            13.09.2019 19:25

            git config —global core.quotepath off

            Пользуйтесь на здоровье :)


  1. KorDen32
    12.09.2019 11:41

    grep -l '.*' ~/* ~/.* | grep -L '.*' ~/* ~/.* 2>/dev/null

    Всё же
    grep -l '.*' ~/* ~/.* 2>/dev/null || grep -L '.*' ~/* ~/.* 2>/dev/null


    1. Oxyd Автор
      13.09.2019 03:53

      Да, так правильнее…


  1. DarthVictor
    12.09.2019 11:41

    А еще есть exa, она не стандартная, зато с подсветкой.


    1. eumorozov
      12.09.2019 11:51

      Кстати, я так и не понял в чем прелесть. Одно время использовал alias ls=exa, но потом перестал, т.к. разницы с ls --color -F почти и нет.


      Какие-то преимущества у exa наверное и есть, но для человека, проработавшего в bash десятилетями, они настолько незначительны, что игра не стоит свеч, по-моему.


      А если относительно темы статьи, то это похоже на читерство. И exa вряд ли распространенный инструмент.


  1. ertaquo
    12.09.2019 11:45

    du -d1 -h .


    1. Oxyd Автор
      13.09.2019 04:03

      du было в первой статье.


  1. amarao
    12.09.2019 11:51

    О да, больше glob'а. Это так неожиданно. /сарказм


    1. edo1h
      12.09.2019 13:02

      вот-вот, странно читать «с помощью XXX», а всю работу выполняет шелл, развернувший *.
      упомянуть об этом способе нужно, конечно, но не преподносить его как 20 разных способов же.


      1. POPSuL
        12.09.2019 13:13

        В некоторых способах можно и без него обойтись, даже в моем варианте с rm. Добавить флаг -r и добавить один символ в grep. Для меня это очевидная альтернатива, но я не написал этот вариант именно в таком исполнении, потому что он может выполняться бесконечно долго.


        1. edo1h
          12.09.2019 13:22

          В некоторых способах можно и без него обойтись

          там, где можно обойтись (и обошлись) — там это отдельный способ. где используется * — один.
          не написали же миллион способов с find, хотя все способы с * можно переписать на find.


  1. DreamingKitten
    12.09.2019 12:33

    Никто не предложил find ????


    1. POPSuL
      12.09.2019 12:45

      Это настолько очевидно, что было в первой статье.


  1. SlavniyTeo
    12.09.2019 13:12

    Не знаю, как так получилось, но в первой статье нет моего второго комментария (забыл нажать кнопку "Опубликовать?").


    Просто на всякий случай напоминаю условия задачи:


    Выведите список файлов в домашней директории максимально возможным количеством способов, без использования ls или его алиасов(1 способ — 1 балл)

    Варианты решения:


    • mc $HOME
    • nautilus $HOME
    • gopen $HOME — можно даже так
    • ...
    • ну не буду же я перечислять все файловые менеджеры


    1. POPSuL
      12.09.2019 13:15

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


      1. SlavniyTeo
        12.09.2019 13:22

        Ну все, что я могу добавить для случая с похереными базовыми утилитами по ssh: chromium-browser "file://$HOME"


        Вообще, я не зря привел условие задачи в своем комментарии.


        1. SlavniyTeo
          12.09.2019 13:28

          Увидел, что в первой статье такой вариант указали за пол часа до меня. Версия с хромиумом в headless режиме очень даже ничего


      1. 027
        12.09.2019 13:50

        А я как-то ковырялся по телнету в роутере, где ls попросту отсутствовал в бизибоксе.


        1. POPSuL
          12.09.2019 14:30

          Да, и такое бывает. А еще бывает когда есть ls, но нет mv/cat/cp/etc… Нужна еще серия статей для поиска альтернатив другим утилитам! :)


          1. 3vi1_0n3
            12.09.2019 22:55
            +2

            Типа такого?
            https://m.habr.com/en/post/145073/
            Там комментарии тоже огонь


            1. POPSuL
              13.09.2019 01:02

              Ну вроде того, но хотелось бы больше извращений как в этой статье :)
              Но статья отличная, спасибо!


            1. Oxyd Автор
              13.09.2019 04:22

              Ох! Какая знатная замена трейсруту! Спасибо за ссылку.


              1. 027
                13.09.2019 19:51

                Знатная замена трейсруту — mtr (my traceroute)
                А тот наколенный скрипт не показывает хопы, которые не отвечают.


  1. SlavniyTeo
    12.09.2019 13:22

    комментарий переехал


  1. pcdesign
    12.09.2019 13:29

    tail -n 0  ~/* ~/.* 2>/dev/null | cut -d '>' -f2
    


  1. larrabee
    12.09.2019 15:28

    diff -r ./ /empty_dir/ | awk -F ':' '{print $2}'

    chown -v -R root:root ./


    1. 027
      12.09.2019 16:56

      chown -v -R root:root ./

      Главное, от рута по рассеянности не запустить. :)
      И мусора в выхлопе много.


      1. Oxyd Автор
        13.09.2019 04:30

        И в директории лезет, по понятным причинам.


        1. 027
          13.09.2019 19:57

          Ну так -R убрать, и не полезет. А зачем там -v, непонятно — chown и так руга… А-а! автор надеялся, что будут запускать таки от рута! )))


  1. Clasen01
    12.09.2019 17:09

    теперь нужны бенчмарки для всех команд, какая из них эффективнее справляется с задачей) (быстрее работает с большим количеством папок)


  1. 027
    12.09.2019 18:01

    теперь нужны бенчмарки

    Прошелся по примерам в первой статье.
    Тестовая дира — плоский каталог, около 15 тыщ файлов.
    Делать лень, взял готовый.
    $ ll | wc -l
    14881

    Выхлоп везде поскипан, естессно.

    Бенчим
    1)
    time for i in ./*  ./.* ; do echo $i ; done
    ...
    real  0m0,263s
    user  0m0,189s
    sys 0m0,051s

    time echo ./* ./.*
    ...
    real  0m0,111s
    user  0m0,070s
    sys 0m0,008s


    2)
    (пришлось устанавливать, искаропка подвела)
    time tree -aiL 1
    ...
    real  0m0,226s
    user  0m0,127s
    sys 0m0,064s


    3)
    time find . -maxdepth 1 -mindepth 1
    ...
    real  0m0,117s
    user  0m0,039s
    sys 0m0,034s
    


    4)
    time du -ad 1 .
    ...
    real  0m0,164s
    user  0m0,027s
    sys 0m0,076s


    5)
    time tar -cvf /dev/null --no-recursion ./* ./.* 2>null
    ...
    real  0m0,265s
    user  0m0,121s
    sys 0m0,111s


    6)
    time perl -e 'use feature "say"; opendir my $dh, "." or die "Could not open . for reading: $!\n"; while (my $thing = readdir $dh) { say $thing; };'
    ...
    real  0m0,112s
    user  0m0,038s
    sys 0m0,029s


    7)
    time echo -e "import os\nfor i in os.listdir('.'): print(i)" | python
    ...
    real  0m0,120s
    user  0m0,032s
    sys 0m0,039s


    Мой вариант:
    time rsync --list-only ./
    ...
    real  0m0,210s
    user  0m0,094s
    sys 0m0,091s


    Сама ls:
    time ls
    ...
    real  0m0,223s
    user  0m0,103s
    sys 0m0,043s


    1. Sly_tom_cat
      12.09.2019 19:24

      Всего чего угодно ожидал но не того что питон и перл порвут ls…


      1. 027
        12.09.2019 19:31
        +1

        На прогретом кэше — почему нет? Чтением каталога все равно сишные программы занимаются, интерпретаторы чисто обертка. Баш, кстати, тоже интерпретатор.

        А ls, что ls… оно по умолчанию, еще и сортирует. А без сортировки, вот:

        time ls -f
        ...
        real	0m0,114s
        user	0m0,030s
        sys	0m0,026s

        И кто знает, что там набенчится, если перл заставить сорт… Черт! Вспомнился чудный перл с баша:
        * Daemon потыкал палочкой в wd
        яя
        а чиво станет с перлом, если в хеш загнать 2 гига данных и заставить перл его сортировать?
        будет сортировать
        неожиданно


      1. POPSuL
        13.09.2019 01:05
        +1

        Удалено, я слепой


    1. Aldrog
      13.09.2019 09:38

      Мне кажется или в вариантах с глобами правильнее делать time bash -c '...', чтобы время разворачивания глобов тоже учитывалось?


      1. 027
        13.09.2019 20:07

        Нет, разброс от запуска к запуску больше, чем разница между вариантами с bash -c и без.
        Правильнее делать многократные измерения с усреднением, но мне лень. :)


    1. Aldrog
      14.09.2019 14:18

      У меня так (time из zsh):


      Заголовок спойлера

      1) Запускал через bash, потому что zsh отказывается замерять время работы echo напрямую


      bash -c 'for i in ./*  ./.* ; do echo $i ; done'  0.01s user 0.00s system 97% cpu 0.011 total

      bash -c 'echo ./* ./.*'  0.01s user 0.00s system 96% cpu 0.009 total

      2) Тоже пришлось устанавливать


      tree -aiL 1  0.01s user 0.00s system 96% cpu 0.010 total

      3)


      find . -maxdepth 1 -mindepth 1  0.01s user 0.00s system 95% cpu 0.008 total

      4) Ожидаемо сильно страдает от большого числа вложенных директорий


      du -ad 1 .  1.46s user 17.90s system 6% cpu 4:38.79 total

      5)


      tar -cvf /dev/null --no-recursion ./* ./.* 2> null  0.12s user 0.00s system 90% cpu 0.134 total

      6)


      perl -e   0.01s user 0.00s system 23% cpu 0.024 total

      7)


      python  0.03s user 0.01s system 90% cpu 0.034 total

      rsync


      rsync --list-only ./  0.01s user 0.01s system 82% cpu 0.016 total

      ls


      ls --color=auto  0.01s user 0.01s system 5% cpu 0.259 total

      ls --color=no  0.01s user 0.00s system 95% cpu 0.009 total


  1. Livid
    12.09.2019 20:20

    Таки все варианты с глоббингом это один вариант с глоббингом, echo ./* ./.*. Таки список файлов в таком варианте даёт шелл, а не что-нибудь.


    1. 027
      12.09.2019 20:32

      Таки да — уже в нескольких местах мысль повторили.


  1. drbald
    12.09.2019 20:38

    Удивительно, что всё еще нет картинки про буханку хлеба и троллейбус.


    1. 027
      12.09.2019 20:46

      И действительно, как это ни один мимокрокодил, ничего тут не понявший, не набижал с буханкою наперевес?.. (снедаемый эффектом Даннинга-Крюгера)


    1. Oxyd Автор
      13.09.2019 04:32
      +2

      А зачем? Это же развлечение чисто Just for fun. Ну, как brainfuck какой-нибудь.


  1. celebrate
    13.09.2019 10:36

    А почему докер не упомянули?

    docker run --rm -v `pwd`:/tmp busybox ls /tmp


    1. SlavniyTeo
      13.09.2019 13:29

      Потому что Вы используете ls, что было запрещено правилами?