Нетипичный «ls» или как развлекаются линуксоиды

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

    Такое же задание чуть позже прилетело в ещё один чат, и вот что из этого получилось:

    1. echo и print


    for i in ~/*  ~/.* ; do echo $i ; done

    Ровно то же самое выдаст замена команды echo на print.
    На самом деле можно обойтись и без цикла, получится не так красиво, но под условие задачи вполне подходит.

    echo ~/* ~/.*

    2. tree


    Более очевидный способ — использовать tree, который практически ls если подобрать правильные ключи.

    tree -aiL 1 ~

    3. find


    Тоже более чем очевидное решение.

    find ~ -maxdepth 1 -mindepth 1

    4. du


    Да, про du народ не забыл.

    du -ad 1 ~

    5. tar


    Переходим к водным процедурам тонким извращениям.

    tar -cvf /dev/null --no-recursion ~/* ~/.* 2>null

    6. 7. Perl и Python


    Так как в условии задачи я забыл поставить ограничение на интерпретаторы, которые в современных линуксах обычно есть в системе из коробки, то кашевары и змееводы не смогли остаться в стороне:
    Perl:

    perl -e 'use feature "say"; opendir my $dh, "." or die "Could not open . for reading: $!\n"; while (my $thing = readdir $dh) { say $thing; };'

    Python:

    echo -e "import os\nfor i in os.listdir(os.getenv('HOME')): print(i)" | python

    Вне конкурса


    Выдали на гора даже исходник на C, но хоть компилятор и присутствует практически везде, кроме всяких emmbedded дистрибутивов, я посчитал это уж совсем полным беспределом. ;-)

    #include <stdio.h>
    #include <stdlib.h>
    #include <dirent.h>
    
    #define HOME getenv("HOME")
    
    int main(int argc, char const *argv[])
    {
        struct dirent *dp;
        DIR *dir = opendir(HOME);
            while ((dp = readdir(dir)) != NULL)
                printf("%s\n", dp->d_name);
        closedir(dir);
    
        return 0;
    }

    P.S.


    Вероятно, где-то в coreutils/findutils участники развлекухи что-то пропустили. Были неудачные попытки использовать less/more, но может у хабровчан тоже появились идеи по нестандартному использованию стандартных утилит.

    Upd. 1


    Спасибо хабр! Комменты, это просто праздник какой-то! И по их мотивам я готовлю новый пост. Оставайтесь на связи!

    Upd. 2


    Как я и обещал, вторая часть «Марлезонского балета».
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

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

      +2
      cd ~; vi .
      (zsh) ~/ [tab][tab]
        +1

        [tab][tab] — слишком интерактивно


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

        К сожалению, выведет пару лишних строк.

          0
          На FreeBSD не работает такое…
        +2

        Конечно пропустили. В coreutils, например, есть команда dir. :)

          +2
          dir ~
            +2
            vim .
              +2
              cp ~/ <Tab><Tab>
              mv ~/ <Tab><Tab>
              dd if=~/ <Tab><Tab>
              и т.п.
                0
                можно несуществующую команду:
                a ~/[TAB][TAB]
                ! ~/[TAB][TAB]
                можно для текущей директории такое:
                ![TAB][TAB][TAB]

                PS. Пока эксперементировал, нашел devbash :)
                `/[TAB][TAB]

                выдает:

                binbash: bad substitution: no closing "`" in `/bin
                etcbash: bad substitution: no closing "`" in `/etc
                lib64bash: bad substitution: no closing "`" in `/lib64
                mntbash: bad substitution: no closing "`" in `/mnt
                runbash: bad substitution: no closing "`" in `/run
                tmpbash: bad substitution: no closing "`" in `/tmp

                bootbash: bad substitution: no closing "`" in `/boot
                homebash: bad substitution: no closing "`" in `/home
                libx32bash: bad substitution: no closing "`" in `/libx32
                optbash: bad substitution: no closing "`" in `/opt
                sbinbash: bad substitution: no closing "`" in `/sbin
                usrbash: bad substitution: no closing "`" in `/usr

                cdrombash: bad substitution: no closing "`" in `/cdrom
                libbash: bad substitution: no closing "`" in `/lib
                lost+foundbash: bad substitution: no closing "`" in `/lost+found
                procbash: bad substitution: no closing "`" in `/proc
                srvbash: bad substitution: no closing "`" in `/srv
                varbash: bad substitution: no closing "`" in `/var

                devbash: bad substitution: no closing "`" in `/dev
                lib32bash: bad substitution: no closing "`" in `/lib32
                mediabash: bad substitution: no closing "`" in `/media
                rootbash: bad substitution: no closing "`" in `/root
                sysbash: bad substitution: no closing "`" in `/sys

                  0
                  Я за эти клавиатурные таб-таб каюсь, ибо совсем забыл, что:
                  • автоподстановка не является всеобщим правилом для *никсов, а есть только там, где она сознательно реализована мейнтейнером для конкретного окружения конкретной версии*;
                  • есть способ посмотреть без выстукивания по клаве, что выдаст автоподстановка в разных ситуациях, а именно — команда баша compgen.

                  *) например, автодополнение в моей системе живет тут: /etc/bash_completion и тут: /etc/bash_completion.d.
                    0
                    Заинтересовался автодополнением.)
                    А с помощью complete можно эту задачу решить?
                  0
                  «Что угодно + ПРОБЕЛ + ТАБ» — все файлы.
                  «Что угодно + ПРОБЕЛ + ТОЧКА + ТАБ» — все скрытые каталоги и файлы.
                  +22
                  Так конечно делать не нужно, но если уж совсем нет других вариантов…
                  Я предупреждал
                  yes "n" | rm -i $HOME/* $HOME/.* 2>&1 | grep -o "$HOME[^»'’]*"
                  

                    +1
                    Можно и чуть покороче))
                    rm -fv ~/* 2> /dev/null
                      +2
                      Ну и шуточки у вас. ;-)
                      0
                      Я предупреждал

                      Но мы же все делаем бэкап $HOME, правда?
                        +3

                        Конечно. В $HOME/.backup :-)

                          +1
                          А-а-а! Ты знал!!!
                          $ ls -1 ~
                          ...
                          027
                          1
                          backup
                          projects
                          scripts
                          Видео
                          Документы
                          ...
                          
                            0

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

                              +1
                              А-а-а! Ты знал!!!
                              0
                              А чё, так можно было, что ли?(с)
                        0
                        Самый простой способ — создать архив файлов в нужной директории а потом вывести листинг архива. Это поддерживает куча архиваторов. Можно и рекурсивно.
                          +2

                          Что-то подобное через tar как раз и описано, только листинг выводится при упаковке

                          +1
                          grep "" -lr .
                          less .
                          
                            0
                            Вышенаписанные варианты
                            $ less .
                            $ vi .
                            у меня выводят:
                            . is a directory

                            grep "" -lr .
                            выводит все потроха рекурсивно (не уверен, что это соответствует условию задачи)
                              0

                              Странно, что less себя так ведёт, может зависит от шела? У меня в bash показывает содержание текущей директории.


                              С grep можно попробовать такой вариант grep "" -l ./*, правда формат вывода директорий, не очень красив.

                                0
                                Странно, что less себя так ведёт, может зависит от шела?

                                Наверное. У меня
                                $ bash --version
                                GNU bash, версия 4.4.20(1)-release (x86_64-pc-linux-gnu)
                                $ lsb_release -d
                                Description:	Linux Mint 19.1 Tessa


                                «nano .» то же самое пишет, разве что по-русски.
                                  0

                                  У меня в Fedora работает, а у коллеги на Mint нет. :)

                                    0
                                    Стало быть, способ не универсален, только и всего.
                                    0

                                    Проверять надо при помощи type less (у меня fish, не помню, как в bash записывается, кажется так же) и less -V.

                                      0

                                      И от шелла и не от шелла. В Fedora переменная LESSOPEN определяется на скрипт, выводящий в случае директории вывод ls.


                                      Детали
                                      [user@localhost ~]$ rpm -ql less
                                      /etc/profile.d/less.csh
                                      /etc/profile.d/less.sh
                                      /usr/bin/less
                                      ...
                                      /usr/bin/lesspipe.sh
                                      ...
                                      [user@localhost ~]$ cat /etc/profile.d/less.sh 
                                      # less initialization script (sh)
                                      # All less.*sh files should have the same semantics!
                                      if [ -z "$LESSOPEN" ] && [ -x /usr/bin/lesspipe.sh ]; then
                                          # The '||' here is intentional, see rhbz#1254837.
                                          export LESSOPEN="||/usr/bin/lesspipe.sh %s"
                                      fi
                                      [user@localhost ~]$ cat /usr/bin/lesspipe.sh                
                                      #!/bin/sh
                                      ...
                                      # The script should return zero if the output was valid and non-zero
                                      # otherwise, so less could detect even a valid empty output
                                      # (for example while uncompressing gzipped empty file).
                                      # For backward-compatibility, this is not required by default. To turn
                                      # this functionality there should be another vertical bar (|) straight
                                      # after the first one in the LESSOPEN environment variable:
                                      # export LESSOPEN="||/usr/bin/lesspipe.sh %s"
                                      ...
                                      if [ -d "$1" ] ; then
                                              ls -alF -- "$1"
                                              exit $?
                                      fi
                                      ...

                                      Аналогичное сделано (несколько другими скриптами правда) и в RH 7 (Centos 7) и в OpenSUSE

                                +5
                                rsync --list-only ~/
                                  +3
                                  Я считаю, grep и stat незаслуженно забыли:
                                  grep -l '.*' ./*
                                  stat ./*
                                  
                                    +2
                                    stat незаслуженно забыли

                                    stat дает чрезмерно говорливый выхлоп, а в задаче надо просто список файлов.
                                    Тогда уж лучше file:
                                    file ~/*

                                    Но этот способ не показывает скрытые файлы (как и все иные, основанные на разворачивании звездочки интерпретатором). Может, как-то можно через переменные окружения на это повлиять?
                                      0
                                      file ~/* ~/.*
                                      
                                        0
                                        Ну или так.
                                          +1
                                          file  -0 * |cut -f 1 -s -d ''
                                        0
                                        Говорливость stat регулируется, можно выводить от только имени до хотя json какого нибудь.
                                        Например:
                                        stat -c "%A %G:%U %s %x %n" * \.*
                                          +3
                                          shopt -s dotglob
                                          включит скрытые файлы в маску *
                                            0
                                            Ну говорливый. Говорилка-то угоманивается… ;-)
                                            stat ~/* ~/.*|grep "/home"|awk '{print $2}
                                              0
                                              Ага, точно. Будто слишком говорливой теще заткнули рот кляпом, а когда это не помогло, стали душить удавкой. :)
                                              Удawkой, кхм…
                                                0
                                                Мы их душили, душили! Душили, Душили!
                                                © Шариков.
                                            +1
                                            grep так не покажет пустые файлы
                                            grep -l '.*' ./* || grep -L '.*' ./*
                                            0

                                            gzip -cv1 ./* | gzip -l

                                              0
                                              Что-то он у меня в хомяке чуть ли не треть файлов не показал…
                                              0
                                              head -n 0 -v ./*
                                                +2
                                                echo -e «import os\nfor i in os.listdir(os.getenv('HOME')): print(i)» | python

                                                Так аккуратнее, на мой взгляд:
                                                python -c "import os;  print(os.listdir('.'))"
                                                  0
                                                  1. echo и print

                                                  Эти команды не идентичны. Возможно Вы имели в виду printf, но она может сбоить в некоторых случаях, хотя echo — тоже.


                                                  1. tar

                                                  У вас мешанина в примере — /dev/null и null.


                                                  1. Perl

                                                  Нет нужды использовать последние фичи языка, но можно использовать внутренние возможности:


                                                  perl -le '$d = "."; opendir D, $d or die "Could not open $d for reading: $!\n"; print while (readdir D)'

                                                  И, кстати, вот еще один перловый ls:


                                                  perl -le 'print while <.* *>'
                                                    0
                                                    На случай если есть руби из коробки:
                                                    ruby -e 'puts Dir.entries "."'
                                                      0
                                                      На случай, если есть php в коробке.

                                                      Для текущей:
                                                      php -r 'print_r(scandir("."));'

                                                      Для домашней:
                                                      php -r 'print_r(scandir($argv[1]));' -- ~

                                                      Для всякой:
                                                      php -r 'print_r(scandir($argv[1]));' -- <some_dir>
                                                        0
                                                        Интересно есть ли дистрибутив, в котором пхп прямо в базовой поставке)
                                                          0
                                                          Любой, снабженный веб-мордой на php. Openmediavault, например.
                                                    0
                                                    [любые символы][space][tab][tab]
                                                    GNU bash, version 5.0.7(1)-release
                                                    urxvt v9.22
                                                      0
                                                      любые

                                                      У меня, как минимум, не работает с кавычками и апострофом.

                                                        0
                                                        Я утрировал. Не совсем любые.
                                                          0

                                                          О, символы вообще не нужны! Достаточно просто пробела.

                                                            0
                                                            У меня не воспроизводится (
                                                              0
                                                              Зависит от окружения, стало быть. Сейчас потыкал на контейнере с убунтой 14.04 — совсем не так реагирует на колочение таба. Плохой способ.
                                                        +1
                                                        getfacl ~/* ~/.*
                                                          0
                                                          getfacl ~/* ~/.* | grep "# file" | awk '{print $3}'
                                                          +13
                                                          ls -i /home
                                                          529589 test

                                                          debugfs /dev/sda1
                                                          debugfs: stat <529589>
                                                          Inode: 529589 Type: directory Mode: 0755 Flags: 0x80000
                                                          Generation: 2678704405 Version: 0x00000000:00000007
                                                          User: 1000 Group: 1000 Project: 0 Size: 4096
                                                          File ACL: 0
                                                          Links: 4 Blockcount: 8
                                                          Fragment: Address: 0 Number: 0 Size: 0
                                                          ctime: 0x5d721b09:c9c4305c — Fri Sep 6 08:38:33 2019
                                                          atime: 0x5d78e0f5:a027932c — Wed Sep 11 11:56:37 2019
                                                          mtime: 0x5d721b09:c9c4305c — Fri Sep 6 08:38:33 2019
                                                          crtime: 0x5d721abd:243d5800 — Fri Sep 6 08:37:17 2019
                                                          Size of extra inode fields: 32
                                                          Inode checksum: 0xa0aa0f22
                                                          EXTENTS:
                                                          (0):2106181

                                                          берем
                                                          (0):2106181

                                                          dd if=/dev/sda1 of=image.dd bs=4096 count=1 skip=2106181

                                                          hexdump -C image.dd | awk '{print $18}'
                                                          |................|
                                                          |................|
                                                          |.profile........|
                                                          |.bashrc.........|
                                                          |.bash_logout....|
                                                          |.....cache......|
                                                          |.....gnupg......|
                                                          |.....sudo_as_adm|
                                                          |in_successful...|
                                                          |................|

                                                          |............&..W|

                                                          :)
                                                            0
                                                            Круто! Реально круто! Осталось понять как избавиться от ls -i…
                                                              0

                                                              Можно через stat узнать inode

                                                              0
                                                              К сожалению, не будет работать на ext4, если в директории больше 4 кластеров. Там включится Hash Tree и вместо имен файлов увидим только хэши.
                                                              +1
                                                              stat *|awk '/File:/{print $2}'
                                                                0
                                                                Хорошо, до той поры пока не наткнётся на русскую локаль… ;-) Ну или например китайскую.
                                                                  0

                                                                  LANG=C stat ... никто не отменял :)

                                                                    0
                                                                    О, кстати!
                                                                    Кто объяснит, почему в подобных конструкциях после задания переменной не нужно ставить точку с запятой? Это же отдельная команда, по идее.
                                                                      0

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


                                                                      LANG=C stat . | LANG=C other-command
                                                                        0
                                                                        Спасибо. А не подскажете, где про это можно почитать? Это же не bash-специфичное поведение?
                                                                          0

                                                                          Это работает даже в sh.
                                                                          Почитать об этом можно в разделе https://help.ubuntu.com/community/EnvironmentVariables#Bash.27s_quick_assignment_and_inheritance_trick
                                                                          Ну и вообще, вся статья полезна.

                                                                            +1
                                                                            Это Bourne shell-совместимое поведение.
                                                                            Не будет работать в C-shell'ах
                                                                            Там потребуется выполнять env, set или setenv соответственно для изменения переменной окружения, установки сессионной переменной и экспорта переменной.
                                                                              0

                                                                              И в fish тоже по другому работает: env LANG=C ls
                                                                              Я уже несколько лет как перешел с bash и zsh на fish. Не знаю откуда у меня такая настойчивость, первые года два ломало, а теперь втянулся и нравится.


                                                                              bash — вообще считаю недоразумением. Сколько лет можно чинить теряющуюся историю?.. Эта проблема существует уже наверное не менее десятилетия. Миллионы хаков напридумано для костыльного исправления этой ошибки, вышел один или два мажорных релиза bash, а воз и ныне там...

                                                                                0
                                                                                А zsh-то в чём провинился?
                                                                                  0

                                                                                  Не знаю, просто мне он всегда как-то не нравился. Не по какой-то конкретной причине, просто идиосинкразия какая-то. Не нравится и все, не могу объяснить.

                                                                                  0
                                                                                  Я уже несколько лет как перешел с bash и zsh на fish. Не знаю откуда у меня такая настойчивость, первые года два ломало, а теперь втянулся и нравится.

                                                                                  Два года? Похоже, эта ваша рыба заливная! :)
                                                                                    0

                                                                                    Честно говоря, единственная вещь, которая напрягала эти два года — отсутствие Ctrl-R в fish. Точнее, неточная эмуляции этого механизма при помощи fzf.


                                                                                    Когда работаешь с bash где-то с 1996 года, всякие bash'евские приемы работы начинают жить где-то уже в пальцах. Но два года оказалось достаточно, чтобы перебить старые привычки.


                                                                                    Все-такие fish — это какой-то шаг вперед. bash и zsh кажутся отставшими от времени и слишком эклектичными. PowerShell кажется наоборот очередным неудобным overengineering от Microsoft.


                                                                                    fish ­— этакий разумный компромисс между эклектичной олдфажностью и современностью.

                                                                              0
                                                                              Хм… А почему вот это не работает?
                                                                              $ LANG=C echo $LANG
                                                                              ru_RU.UTF-8
                                                                              

                                                                              $ LANG=C /bin/echo $LANG
                                                                              ru_RU.UTF-8
                                                                              
                                                                                0

                                                                                Потому что $LANG это переменная, которая уже объявлена, и при выполнении этой команды она "разворачивается" в значение ru_RU.UTF-8.


                                                                                upd: именно поэтому я и показал пример с getenv

                                                                                  0
                                                                                  Потому что $LANG это переменная, которая уже объявлена, и при выполнении этой команды она «разворачивается» в значение ru_RU.UTF-8.

                                                                                  Как же так? Я ее только что переопределил из 'ru_RU.UTF-8' в 'C'.
                                                                                  Почему-то echo это игнорирует, а вот, скажем, man, radeontop используют значение 'C'.
                                                                                    0

                                                                                    Потому-что в баше переменные "разворачиваются" в значение до запуска самой программы. По схожему принципу и работает glob, т.е. вы напишете cat *, но баш на самом деле сам прочитает содержимое директории, и выполнит что-то вроде cat a.txt b.txt c.txt somedir.
                                                                                    Почему radeontop работает — я не знаю, возможно он работает совсем не так как вы ожидаете, и просто не замечаете это (я за зеленых, поэтому такие тулзы ни разу в жизни не использовал).

                                                                                      +2
                                                                                      Почему-то echo это игнорирует

                                                                                      Именно так, потому что echo не «интересуют» переменные окружения.
                                                                                      Пример
                                                                                      EDITOR=mcedit crontab -e
                                                                                      откроет cron в mcedit
                                                                                      EDITOR=vi crontab -e
                                                                                      откроет cron в vi
                                                                                      но
                                                                                      $ EDITOR=vi echo "one: [$EDITOR]"
                                                                                      one: []

                                                                                      echo просто пофиг на нашу переменную окружения.
                                                                                      Но мы можем задать её как переменную оболочки и ограничить область действия (Bourne shell-совместимое поведение):
                                                                                      $ (EDITOR=vi; echo "one: [$EDITOR"]); echo "two: [$EDITOR]"
                                                                                      one: [vi]
                                                                                      two: []

                                                                                      аналогично для запрашиваемого примера:
                                                                                      $ (LANG=C; /bin/echo $LANG); /bin/echo $LANG
                                                                                      C
                                                                                      en_US.UTF-8


                                                                                        0
                                                                                        Именно так, потому что echo не «интересуют» переменные окружения.

                                                                                        Я понял так, что модифицированные переменные окружения выдаются программе в виде копии и исключительно для нужд настройки поведения.
                                                                                        $LANG интерпретатор берет из текущего окружения для всего сеанса ( а echo тут вообще ничего не решает).
                                                                                        Если бы удалось заставить echo ругаться на что-либо, тогда модифицированное значение переменной LANG влияло бы на язык сообщений. Как это и происходит в моей системе с man, nmap и radeontop, которые обучены русскому.

                                                                                        Трюк, походу, не bash-специфичный — в dash переключение языка срабатывает.
                                                                                          0

                                                                                          echo — встроенная команда bash (builtin). То есть, при выполнении echo не будет порожден новый процесс, в котором будет запущена программа /bin/echo.


                                                                                          LANG=C влияет на порожденные процессы. Например, LANG=C ls приводит к порождению процесса запускающего /bin/ls, и в этом процессе уже будет модифицированное окружение.

                                                                                            0
                                                                                            echo — встроенная команда bash (builtin). То есть, при выполнении echo не будет порожден новый процесс, в котором будет запущена программа /bin/echo.

                                                                                            Я приводил в исходном каменте оба варианта, со встроенным эхом и с /bin/echo. Поведение одинаковое.

                                                                                            встроенная команда bash… не будет порожден новый процесс

                                                                                            Вы это точно знаете или предполагаете?
                                                                                              0
                                                                                              Кстати, подляна изрядная, эти одноименные встроенные команды. Когда не знаешь об этом, массу времени можно потерять, ругая ни в чем не повинного составителя мана утилиты.
                                                                                                0

                                                                                                Ах, да, прав комментатор про то, что bash подставляет значения переменных при вызове. Конечно, когда мы пишем cmd $VAR любой shell обязан подставить $VAR до вызова команды.


                                                                                                Вы это точно знаете или предполагаете?

                                                                                                Конечно уверен. На то они и builtins, к чему тратить ресурсы системы на порождение нового процесса?..


                                                                                                Поэтому при отладке каких-то проблем со скриптами и т.п., что я делаю первым делом — запускаю type ls или type cat и т.д., чтобы знать точно, что не имею дело с алиасом или командой, которая взялась не из стандартного пути.

                                                                                                  0
                                                                                                  Конечно уверен. На то они и builtins, к чему тратить ресурсы системы на порождение нового процесса?..

                                                                                                  Уверенность на основе рассуждения есть предположение. :) Ну да бог с ним. Дело тут совсем не в отдельности процесса.

                                                                                                  Ах, да, прав комментатор про то, что bash подставляет значения переменных при вызове. Конечно, когда мы пишем cmd $VAR любой shell обязан подставить $VAR до вызова команды.

                                                                                                  Отож! Он идет по строке справа налево, натыкается на $LANG, рожает указатель (наверное, я в сях не силен) и тупо скармливает его эху. До модифицированного одноразового окружения ему дела нет.
                                                                                                  А внешне кажется, что это эхо игнорирует, зараза такая своенравная. :)
                                                                                                    0
                                                                                                    Уверенность на основе рассуждения есть предположение. :) Ну да бог с ним. Дело тут совсем не в отдельности процесса.

                                                                                                    Ну, если бы shell не использовал builtins, то, например, такая команда как cd не имела бы смысла: она бы меняла только текущий каталог порожденного процесса, и в shell не было бы никакой возможности перейти в другой каталог.


                                                                                                    А так полагаю, что существует много нюансов. Когда-то я целиком читал документацию по bash. Но это было наверное 20 лет назад, и много мелких нюансов я уже забыл. Возможно, для каких-то команд builtins используются только в интерактивном режиме. Беглый просмотр man bash по диагонали не дал подтверждения, надо внимательно читать его целиком, а он огромный.

                                                                                                    0
                                                                                                    запускаю type ls или type cat и т.д., чтобы знать точно, что не имею дело с алиасом или командой, которая взялась не из стандартного пути.

                                                                                                    Кстати, есть оч. полезная команда в баше:
                                                                                                    compgen -c will list all the commands you could run.
                                                                                                    compgen -a will list all the aliases you could run.
                                                                                                    compgen -b will list all the built-ins you could run.
                                                                                                    compgen -k will list all the keywords you could run.
                                                                                                    compgen -A function will list all the functions you could run.
                                                                                                    compgen -A function -abck will list all the above in one go.

                                                                                                    В частности, вот так можно отловить дублирующуюся команду:
                                                                                                    $ compgen -c | grep -E '^time$'
                                                                                                    time
                                                                                                    time

                                                                                                    Попалась, зараза!
                                                                                                      0
                                                                                                      $ type -a time
                                                                                                      time is a shell keyword
                                                                                                      time is /usr/bin/time
                                                                                                      
                                                                                                        0
                                                                                                        О!
                                                                                                        Сенькс.
                                                                                                        Неисчислимы заковыристые ходы, придуманные в те давние времена, когда компьютеры были большими, а сообщество маленьким.
                                                                                                        Множество частных, подробно ориентированных штучек-дрючек, и никто не ведал, что скоро придет диавол под личиной multimedia, и пожрет все, до чего дотянется мягкими, липкими, необъятными в своих слоях абстракций лапищами…
                                                                                                  0
                                                                                                  у меня echo — файл в bin
                                                                                                    0

                                                                                                    Да, она есть во всех системах из каких-то соображений. Полагаю, чтобы в пользовательских программах не ломался код типа:
                                                                                                    system("echo Hello world").


                                                                                                    Но в shell запустится builtin. /bin/echo запустится, только если писать полный путь: /bin/echo Hello world.

                                                                                                      0
                                                                                                      Да, она есть во всех системах из каких-то соображений. Полагаю, чтобы в пользовательских программах не ломался код типа:
                                                                                                      system("echo Hello world").

                                                                                                      Если в путях есть /bin ничего не сломается. А так должно быть обязательно. Ну, если это не наколенная эмбедовка от васяна, понятно.

                                                                                                      Соображения я встечал такое: большее быстродействие и меньший жор. Вызов внешней утилиты в любом случае накладно. К тому же встроенные нередко более убогие и потому скоростные.
                                                                                                        0
                                                                                                        Действительно ,)
                                                                                                        Для printf, kill, pwd, test — тоже самое.
                                                                                                        Команды делаются встроенными либо из соображений производительности — встроенные команды исполняются быстрее, чем внешние, которые, как правило, запускаются в дочернем процессе, либо из-за необходимости прямого доступа к внутренним структурам командного интерпретатора.
                                                                                                        0
                                                                                                        у меня echo — файл в bin

                                                                                                        У меня и то, и другое:
                                                                                                        $ compgen -c | grep -E '^echo$'
                                                                                                        echo
                                                                                                        echo
                                                                                                        
                                                                                                        $ which echo
                                                                                                        /bin/echo
                                                                                                        
                                                                                                        $ type echo
                                                                                                        echo — это встроенная команда bash
                                                                                                          0
                                                                                                          возможно, было бы удобно их с индексом запускать:
                                                                                                          echo[0]
                                                                                                          echo[1]
                                                                                                            0
                                                                                                            Это как?
                                                                                                              0
                                                                                                              Я имею ввиду, если бы баш позволял.
                                                                                                              [0] — внутренняя
                                                                                                              [1] — внешняя
                                                                                                              Ключевое слово — возможно.

                                                                                                              Хотя есть команда command -p
                                                                                                                0

                                                                                                                Shell и так позволяет запускать любой вариант, было бы странно иначе.
                                                                                                                Просто echo — запускает builtin. /bin/echo запускает /bin/echo.


                                                                                                                Если кто-то или что-то переопределило echo, то builtin echo явно запустит builtin.

                                                                                  0
                                                                                  git init . ; git status

                                                                                  Будет немного лишнего, но можно отфильтровать.
                                                                                    +1
                                                                                    Чуток поправлю.
                                                                                    git init . ; git status; rm -rf .git
                                                                                    +1

                                                                                    Очень простая, но реальная задача:
                                                                                    веб-камера с записью "сошла с ума" и вместо записи по движению скинула на флэшку непрерывную запись целой недели. ~20 тыс. файлов. ФС fat32.
                                                                                    ls (просто) в папке DCIM ничего не выводит (думает минут 5, потом убивается системой).
                                                                                    И вот тут выясняется, что ls написан внутри очень неплохо! Он не получает "список всего", а потом накладывает фильтр, а сразу фильтрует при выводе на экран. В итоге ls "20190901*" и т.д. вполне сработали! (последующий rm так же сработал по тому же паттерну)

                                                                                      0

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

                                                                                        0
                                                                                        Двойные кавычки спасут отца русской демократии, как в примере выше.
                                                                                        0
                                                                                        Рекомендую вам использовать утилиту find в подобных случаях.
                                                                                          +1

                                                                                          Даём команду на интерактивное удаление /home/username (rm -i), и генерируем для неё "интерактивный" ответ сначала из одного "y" (для подтверждения рекурсивного спуска в ~), и затем в цикле "n" (для отказа рекурсивного спуска на более нижние уровни и отказа удаления):


                                                                                          (echo y; yes n) | rm -ir ~

                                                                                          Улучшенный вариант с последующей чисткой лога от ненужного текста:


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

                                                                                            Upd: Извиняюсь, проглядел такое же решение в более раннем комменте под спойлером

                                                                                              0
                                                                                              Зато sed ещё пока никто не использовал. ;-)
                                                                                            0

                                                                                            hdfs dfs -ls

                                                                                              +4
                                                                                              без использования ls

                                                                                              «Ты видишь суслика? И я не вижу.»
                                                                                              $'\x6c\x73' $'\x2d\x61'
                                                                                                0
                                                                                                Не тот человек взял ник Cheater ;-)
                                                                                                0
                                                                                                Для FreeBSD:
                                                                                                cat ~ |strings |xargs -IX sh -c 'test -e X && echo X'

                                                                                                Но не работает с каталогами и файлами, содержащими в имени перевод строки.
                                                                                                  0
                                                                                                  О, как раз хотел добавить
                                                                                                  cat . |strings
                                                                                                  т.к. мало кто знает об этой фиче. Однажды выручила, когда нужно было сделать список файлов на удаление из каталога, где было несколько десятков миллионов файлов и ls просто вешал сервер.

                                                                                                  Но именно ваш вариант не все файлы выводит и не работает еще с файлами, содержащими скобки.
                                                                                                  0
                                                                                                  lsattr ~/* 2>&1 | grep -Po '/.*'
                                                                                                    0
                                                                                                    printf "%s\n" *
                                                                                                    
                                                                                                      0
                                                                                                      rm -rfv ./*
                                                                                                        0
                                                                                                        На хабре бывают и менее опытные пользователи, чем мы с вами. Могут и не распознать патч Бармина, в миниатюре. ;-)
                                                                                                          +2
                                                                                                          Все нормально. Так учатся плавать щенки закаляется сталь становятся на ноги тру-линуксоиды.
                                                                                                        0
                                                                                                        python -m http.server > /dev/null & export PID=$(echo $!) && sleep 1 && curl -s localhost:8000/ | grep -Po '(?<=href=")[^"]*' && kill $PID

                                                                                                        Если вы оказались в сложной жизненной ситуации и у вас есть только Go:


                                                                                                        cat <<EOF | tee /tmp/habr.go | go run /tmp/habr.go
                                                                                                        package main; import ("fmt"; "path/filepath"); func main() {f,_ := filepath.Glob("*"); fmt.Println(f)}
                                                                                                        EOF

                                                                                                        Аналогично, для поклонников современного C++:


                                                                                                        cat <<EOF | c++ -x c++ --std=c++17 -o /tmp/habr - && /tmp/habr
                                                                                                        #include <iostream>
                                                                                                        #include <filesystem>
                                                                                                        using namespace std;
                                                                                                        int main() { for (auto e : filesystem::directory_iterator(".")) cout<<e.path()<<endl; }
                                                                                                        EOF
                                                                                                          0
                                                                                                          compgen -f

                                                                                                          без скрытых файлов
                                                                                                          shuf -e *
                                                                                                            0
                                                                                                            все файлы
                                                                                                            (shopt -s dotglob; shuf -e *)
                                                                                                              +1
                                                                                                              со скрытыми файлами

                                                                                                              shuf -e * .*
                                                                                                              0
                                                                                                              справедливо для gawk
                                                                                                              (shopt -s dotglob; awk -lreaddir 'ENDFILE {print FILENAME}' *)
                                                                                                                0
                                                                                                                mkdir aaa && mv -v ~/* ~/.* aaa && mv aaa/*. aaa/* ~ && rm -r aaa
                                                                                                                  0

                                                                                                                  Тогда уж проще заюзать cp -alv вместо mv, и безопаснее.

                                                                                                                    0
                                                                                                                    Проще использовать ls :)
                                                                                                                    mv — быстрее выполняется, так как не создается копия.
                                                                                                                  +1
                                                                                                                  firefox file://$PWD
                                                                                                                    0

                                                                                                                    Ну, так сходу наверное не получится, firefox скажет "давай мне иксы", но вот такой способ:


                                                                                                                    chromium-browser --headless --no-sandbox --disable-gpu --dump-dom file:///$HOME | awk -F'"' '{print $2}'

                                                                                                                    вполне имеет право на жизнь!
                                                                                                                    Oxyd думаю можно во вторую статью добавить ;)

                                                                                                                      +1
                                                                                                                      От извращенцы!
                                                                                                                      (одобряэ)
                                                                                                                        +1
                                                                                                                        О Да!!! (побежал ставить Chromium)
                                                                                                                      0
                                                                                                                      mc
                                                                                                                      ranger
                                                                                                                      exa

                                                                                                                      wc -c *
                                                                                                                      size *
                                                                                                                      cksum *
                                                                                                                      crc32 *
                                                                                                                      sha1sum *
                                                                                                                      md5sum *
                                                                                                                      sum *
                                                                                                                      

                                                                                                                      Осторожно .)
                                                                                                                      chmod -v -x *
                                                                                                                      chown -v <user> *
                                                                                                                      strip -v *

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

                                                                                                                      Самое читаемое