Pull to refresh

Comments 33

В Debian разница не 4, а 8 К
serge78rus@pcdeb:~$ ls -lh /usr/bin/{test,[}
-rwxr-xr-x 1 root root 59K фев 28  2019 '/usr/bin/['
-rwxr-xr-x 1 root root 51K фев 28  2019  /usr/bin/test

В моей Gentoo округлённые до КиБ размеры совпадают с вашими. Должно быть связано либо с версией coreutils (у меня — 8.32), либо с разрядностью системы (64).

Arch Linux, amd64, coreutils 8.32


-rwxr-xr-x 1 root root 59K Mar  6  2020 '/usr/bin/['
-rwxr-xr-x 1 root root 55K Mar  6  2020  /usr/bin/test
Arch Linux, armv7l, coreutils 8.32-1
-rwxr-xr-x 1 root root 42K апр  2  2020 '/usr/bin/['
-rwxr-xr-x 1 root root 42K апр  2  2020  /usr/bin/test
Когда вы пишете if [ -e /etc/passwd ]; then… эта скобка выступает не синтаксисом оболочки, а просто стандартной командой с чудным именем.

А в bash будет использоваться внутренняя команда
$ help [
[: [ аргумент... ]
    Расчёт условного выражения.
    
    Это синоним встроенной команды test, но последним аргументом должна
    быть скобка «]», соответствующая открывающей «[».

встроенной команды test
это и имелось ввиду, что это отдельная команда (пусть и встроенная), но не синтаксис оболочки.
Синтаксис оболочки это например cmd; cmd или cmd && cmd — в этом плане; и && — синтаксис оболочки.
А [ ] — это оператор test
А в centos 7 они почему-то обе сильно меньше.
[root@pro-sip modules]# ls -l /usr/bin/{\[,test} 
-rwxr-xr-x 1 root root 41488 Nov 16 23:24 /usr/bin/[
-rwxr-xr-x 1 root root 37336 Nov 16 23:24 /usr/bin/test


coreutils.x86_64 8.22-24.el7_9.2
Возможно, не делают что-то, добавленное между 8.22 и 8.30
[1=2] оказывается не более валидно, чем ls-l/tmp.

так test1=2 тоже невалиден, а это более прямой пример
Кто вам суказал, что test1=2 невалиден?

Абсолютно валидная конструкция, хотя, возможно, делающая не то, чего вы хотели.

P.S. А ведь комментарий заплюсован… уже и на Хабре люди перестали думать и перешли на подход TikTok-поколения?
Валидный [фр. valide — важный, действующий] — действительный, действенный, соответствующий требованиям.


В данном случае у нас идёт спор терминологии. Что вы вкладываете в валидность и невалидность?
Смотрим контекст статьи:
Когда вы пишете if [ -e /etc/passwd ]; then .. эта скобка выступает не синтаксисом оболочки, а просто стандартной командой с чудным именем. Обычно она встроена в оболочку, но иногда может реализовываться через /usr/bin/[. Это объясняет многое из ее загадочного поведения, например, почему она чувствительна к пробелам: [1=2] оказывается не более валидно, чем ls-l/tmp.

Таким образом валидность здесь понимается в контексте конструкций командной оболочки Unix.

В этом контексте конструкция test1=2 — вполне валидно:
$ if test1=2 ; then echo "Valid!" ; else echo "Invalid" ; fi
Valid!

В отличие от упомянутого в статье примера ls-l/tmp:
$ if [1=2] ; then echo "Valid!" ; else echo "Invalid" ; fi
bash: 1: command not found
Invalid
$ if ls-l/tmp ; then echo "Valid!" ; else echo "Invalid" ; fi
bash: ls-l/tmp: No such file or directory
Invalid


Но разбираться — это ж думать нужно. А заминусовать — это проще.
Кто вам суказал, что test1=2 невалиден?

Я говорю. Она делает не то, что мне нужно.

В отличие от упомянутого в статье примера ls-l/tmp:


Ну так кто мешает вам сделать несуществующую команду существующей?
$ if ls-l/tmp ; then echo "Valid!" ; else echo "Invalid" ; fi
Я совершенно валидная команда, понял?
Valid!

Подсказать что нужно сделать?

Но разбираться — это ж думать нужно. А заминусовать — это проще.

Вот именно, нужно разбираться, а не придираться к выдумкам.
Кто вам суказал, что test1=2 невалиден?
Она делает не то, что мне нужно.

Nuff said.

А в исходники нельзя было смотреть? Всё-таки, свободное ПО…
Обе собираются из файла test.c, разница в:
  if (LBRACKET)
    {
      /* Recognize --help or --version, but only when invoked in the
         "[" form, when the last argument is not "]".  Use direct
         parsing, rather than parse_long_options, to avoid accepting
         abbreviations.  POSIX allows "[ --help" and "[ --version" to
         have the usual GNU behavior, but it requires "test --help"
         and "test --version" to exit silently with status 0.  */
      if (margc == 2)
        {
          if (STREQ (margv[1], "--help"))
            usage (EXIT_SUCCESS);

          if (STREQ (margv[1], "--version"))
            {
              version_etc (stdout, PROGRAM_NAME, PACKAGE_NAME, Version, AUTHORS,
                           (char *) NULL);
              test_main_return (EXIT_SUCCESS);
            }
        }
      if (margc < 2 || !STREQ (margv[margc - 1], "]"))
        test_syntax_error (_("missing %s"), quote ("]"));

      --margc;
    }

coreutils 8.32
-rwxr-xr-x 1 root root       59888 дек  5 23:55 test
-rwxr-xr-x 1 root root       59888 дек  5 23:55 [

ubuntu 21.04, coreutils 8.32-4ubuntu2

Во-истину BSD-системы проще:


$ ls -li /bin/test /bin/[
72389 -r-xr-xr-x  2 root  wheel  12408 14 Apr 18:08 /bin/[
72389 -r-xr-xr-x  2 root  wheel  12408 14 Apr 18:08 /bin/test
$ doas ldd /bin/test
/bin/test:
    libc.so.7 => /lib/libc.so.7 (0x800247000)
$ uname -srm
FreeBSD 13.0-RELEASE amd64
Ради интереса, freebsd:

[rezdm@rezdm-srv /bin]$ ls -al [ test
-r-xr-xr-x  2 root  wheel  23672 Nov  1  2019 [
-r-xr-xr-x  2 root  wheel  23672 Nov  1  2019 test
[rezdm@rezdm-srv /bin]$ test --version
[rezdm@rezdm-srv /bin]$ test --help
[rezdm@rezdm-srv /bin]$ [ --version ]
[rezdm@rezdm-srv /bin]$ [ --help ]
[rezdm@rezdm-srv /bin]$ man [ | grep -i version
                   is retained for compatibility with previous versions of
     A test utility appeared in Version 7 AT&T UNIX.
[rezdm@rezdm-srv /bin]$ man test | grep -i version
                   is retained for compatibility with previous versions of
     A test utility appeared in Version 7 AT&T UNIX.
[rezdm@rezdm-srv /bin]$ uname -a
FreeBSD rezdm-srv 12.1-RELEASE FreeBSD 12.1-RELEASE r354233 GENERIC  amd64

А в чём смысл запускать [ --… ] (с закрывающей скобкой) и test --…? В статье же написано, что второе работать и не должно (точнее, должно, но только как проверка пустоты строки), а второе может показывать help/version только потому что без закрывающей скобки команда некорректна.

[rezdm@rezdm-srv ~]$ [ --version
-bash: [: missing `]'
[rezdm@rezdm-srv ~]$ [ --help
-bash: [: missing `]'
[rezdm@rezdm-srv ~]$ test -version
[rezdm@rezdm-srv ~]$ test -help
[rezdm@rezdm-srv ~]$ 

И это, кстати, тоже абсолютно ожидаемое поведение в bash независимо от системы (т.к. [ и test присутствуют в виде встроенных команд). Вот /usr/bin/[ --version в GNU/Linux выдаст справку.

А еще бывает так, что coreutils скомпилены в единственный бинарник:
Заголовок спойлера
# ls -l $(realpath $(which {test,[}))
-r-xr-xr-x 1 root root 1765416 Jan  1  1970 /nix/store/cc4nnlspm4pwmp5rvjl6wpy9nyzcsbnr-coreutils-8.31/bin/coreutils
-r-xr-xr-x 1 root root 1765416 Jan  1  1970 /nix/store/cc4nnlspm4pwmp5rvjl6wpy9nyzcsbnr-coreutils-8.31/bin/coreutils

Очень сомневаюсь. Скорее, собраны в один пакет ( образ ).
Это coreutils из моей системы
$ ls -l $(dirname $(realpath $(which [)))
итого 1728
lrwxrwxrwx 1 root root 9 янв 1 1970 '[' -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 b2sum -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 base32 -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 base64 -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 basename -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 basenc -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 cat -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 chcon -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 chgrp -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 chmod -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 chown -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 chroot -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 cksum -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 comm -> coreutils
-r-xr-xr-x 1 root root 1765416 янв 1 1970 coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 cp -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 csplit -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 cut -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 date -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 dd -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 df -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 dir -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 dircolors -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 dirname -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 du -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 echo -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 env -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 expand -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 expr -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 factor -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 false -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 fmt -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 fold -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 groups -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 head -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 hostid -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 id -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 install -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 join -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 kill -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 link -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 ln -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 logname -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 ls -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 md5sum -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 mkdir -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 mkfifo -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 mknod -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 mktemp -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 mv -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 nice -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 nl -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 nohup -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 nproc -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 numfmt -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 od -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 paste -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 pathchk -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 pinky -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 pr -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 printenv -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 printf -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 ptx -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 pwd -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 readlink -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 realpath -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 rm -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 rmdir -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 runcon -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 seq -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 sha1sum -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 sha224sum -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 sha256sum -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 sha384sum -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 sha512sum -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 shred -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 shuf -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 sleep -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 sort -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 split -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 stat -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 stdbuf -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 stty -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 sum -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 sync -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 tac -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 tail -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 tee -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 test -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 timeout -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 touch -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 tr -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 true -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 truncate -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 tsort -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 tty -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 uname -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 unexpand -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 uniq -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 unlink -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 uptime -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 users -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 vdir -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 wc -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 who -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 whoami -> coreutils
lrwxrwxrwx 1 root root 9 янв 1 1970 yes -> coreutils

А ниже хороший пример с busybox
А в busybox все вообще в один файл скомпилено, и что?
Тоже думал, пока не попробовал заменить [ на test в скрипте
Когда вы пишете if [ -e /etc/passwd ]; then… эта скобка выступает не синтаксисом оболочки, а просто стандартной командой с чудным именем
Это, конечно, так, но не всегда — зависит от конкретной оболочки

Перевод не очень.


Поскольку сложно просматривать отделенные исполнительные файлы, я создал собственную копию coreutils и сравнил список функций в каждом:

Тут stripped binaries превратились в отдельные файлы, а простая компиляция (built) в создание своей утилиты.

Sign up to leave a comment.