Ответы:
$ touch ./-c $ 'a \ n12 \ tb' foo $ du -hs * 0 а 12 б 0 фу 0 всего
Как видите, -cфайл был выбран как опция duи не сообщается (и вы видите totalстроку из-за du -c). Кроме того, вызванный файл a\n12\tbзаставляет нас думать, что есть файлы с именем aи b.
$ du -hs -- *
0 a
12 b
0 -c
0 foo
Так-то лучше. По крайней мере, это время -cне принимается в качестве опции.
$ du -hs ./*
0 ./a
12 b
0 ./-c
0 ./foo
Это даже лучше. В ./префикс предотвращает -cот принимаются в качестве опции и отсутствие ./до того, bв выходной указывает на то, что нет bфайла в наличии, но есть файл с символом новой строки (но смотри ниже 1 для дальнейших отступлений на том , что).
Рекомендуется использовать ./префикс, когда это возможно, а если нет и для произвольных данных, вы всегда должны использовать:
cmd -- "$var"
или:
cmd -- $patterns
Если cmdне поддерживается --отметка конца опций, вы должны сообщить об этом автору как об ошибке (кроме случаев, когда это выбрано и задокументировано, например echo).
Есть случаи, когда ./*решает проблемы, которые --этого не делают. Например:
awk -f file.awk -- *
завершается неудачно, если a=b.txtв текущем каталоге вызывается файл (задает для переменной awk aзначение b.txtвместо того, чтобы указывать ей обрабатывать файл).
awk -f file.awk ./*
Не имеет проблемы, потому что ./aне является допустимым именем переменной awk, поэтому ./a=b.txtне воспринимается как присвоение переменной.
cat -- * | wc -l
происходит сбой, если -в текущем каталоге вызывается файл , так как он говорит, что catнужно читать из его стандартного ввода ( -это специально для большинства утилит обработки текста и cd/ pushd).
cat ./* | wc -l
это нормально, потому что ./-не является особенным для cat.
Вещи как:
grep -l -- foo *.txt | wc -l
подсчитывать количество файлов, содержащихся fooневерно, так как предполагается, что имена файлов не содержат символов новой строки ( wc -lподсчитывает символы новой строки, те, которые выводятся grepдля каждого файла и те, что указаны в самих именах файлов). Вы должны использовать вместо:
grep -l foo ./*.txt | grep -c /
(подсчет количества /символов является более надежным, поскольку может быть только один для каждого имени файла).
Для рекурсивного grep, эквивалентный трюк должен использовать:
grep -rl foo .//. | grep -c //
./* может иметь некоторые нежелательные побочные эффекты, хотя.
cat ./*
добавляет еще два символа в файл, поэтому вы быстрее достигнете предела максимального размера аргументов + окружения. И иногда вы не хотите, ./чтобы об этом сообщалось в выводе. Подобно:
grep foo ./*
Будет вывод:
./a.txt: foobar
вместо того:
a.txt: foobar
1 . Я чувствую, что должен остановиться на этом здесь, после обсуждения в комментариях.
$ du -hs ./*
0 ./a
12 b
0 ./-c
0 ./foo
Выше, ./отметка начала каждого файла означает, что мы можем четко определить, где начинается каждое имя файла (в ./) и где оно заканчивается (в новой строке перед следующим ./или концом вывода).
Это означает, что выходные данные du ./*, в отличие от данных, du -- *могут быть надежно проанализированы, хотя и не так легко в сценарии.
Когда вывод идет на терминал, есть еще много способов, которыми имя файла может обмануть вас:
\rперемещает курсор в начало строки, \bперемещает курсор назад, \e[Cвперед (в большинстве терминалов) ...В большинстве шрифтов есть символы Unicode, которые выглядят так же, как и косая черта
$ printf '\u002f \u2044 \u2215 \u2571 \u29F8\n'
/ ⁄ ∕ ╱ ⧸
(посмотрите, как это происходит в вашем браузере).
Пример:
$ touch x 'x ' $'y\bx' $'x\n0\t.\u2215x' $'y\r0\t.\e[Cx'
$ ln x y
$ du -hs ./*
0 ./x
0 ./x
0 ./x
0 .∕x
0 ./x
0 ./x
Много x, но yне хватает.
Некоторые инструменты, такие как GNUls, заменяют непечатаемые символы знаком вопроса (обратите внимание, что ∕(U + 2215), тем не менее, можно печатать), когда вывод отправляется на терминал. GNU duнет.
Есть способы заставить их проявить себя:
$ ls
x x x?0?.∕x y y?0?.?[Cx y?x
$ LC_ALL=C ls
x x?0?.???x x y y?x y?0?.?[Cx
Посмотрите, к чему ∕обратились ???после того, как мы сказали, lsчто наш набор символов был ASCII.
$ du -hs ./* | LC_ALL=C sed -n l
0\t./x$
0\t./x $
0\t./x$
0\t.\342\210\225x$
0\t./y\r0\t.\033[Cx$
0\t./y\bx$
$помечает конец строки, так что мы можем заметить "x"vs "x ", все непечатаемые символы и символы не ASCII представлены последовательностью обратной косой черты (сама обратная косая черта будет представлена двумя обратными косыми чертами), что означает, что она однозначна. Это был GNU sed, он должен быть одинаковым во всех sedреализациях, совместимых с POSIX, но обратите внимание, что некоторые старые sedреализации не так полезны.
$ du -hs ./* | cat -vte
0^I./x$
0^I./x $
0^I./x$
0^I.M-bM-^HM-^Ux$
(не стандартный, но довольно распространенный, также cat -Aс некоторыми реализациями). Это один полезно и использует другое представление , но неоднозначно ( "^I"и <TAB>отображается то же, например).
$ du -hs ./* | od -vtc
0000000 0 \t . / x \n 0 \t . / x \n 0 \t .
0000020 / x \n 0 \t . 342 210 225 x \n 0 \t . / y
0000040 \r 0 \t . 033 [ C x \n 0 \t . / y \b x
0000060 \n
0000061
Этот стандарт является стандартным и однозначным (и последовательным от реализации к реализации), но не так легко читается.
Вы заметите, что yникогда не показывалось выше. Это совершенно не связанная с этим проблемаdu -hs * , которая не имеет ничего общего с именами файлов, но следует отметить: поскольку она duсообщает об использовании диска, она не сообщает о других ссылках на уже указанный файл (не все duреализации ведут себя так, хотя при перечислении жестких ссылок) в командной строке).
[a-z0-9.+-].
/tmp) или в районе с большим количеством дорогих автомобилей ( $HOME), и еще хуже - зайти на сайт вопросов и ответов и сказать, что всегда хорошо не блокировать свой автомобиль, не указав, в каких условиях (в закрытом гараже, сценарий Вы написали, что запускаете самостоятельно только на машине, не подключенной к какой-либо сети или съемному хранилищу ...)
"b "или "a\bb") будет обманывать пользователя на терминале, но не скрипт, анализирующий вывод du ./*. Я, вероятно, должен добавить примечание об этом. Сделаю завтра. Обратите внимание, что раньше я имел в виду привилегированный в общем смысле, а не root(хотя, rootконечно, это относится и к тем более ). переводы строки разрешены, игнорирование их является ошибкой. жуки имеют привычку эксплуатироваться. Вы должны измерить риск в каждом конкретном случае. Хорошая практика кодирования может избежать проблем во многих случаях. Конечно, на SE, мы должны повысить осведомленность.
Нет разницы между a *и ./*с точки зрения того, какие файлы будут перечислены. Единственная разница будет со 2-й формой, каждый файл будет иметь ./префикс косой черты перед ними, что обычно означает текущий каталог.
Помните, что .каталог является сокращенной записью для текущего каталога.
$ ls -la | head -4
total 28864
drwx------. 104 saml saml 12288 Jan 23 20:04 .
drwxr-xr-x. 4 root root 4096 Jul 8 2013 ..
-rw-rw-r--. 1 saml saml 972 Oct 6 20:26 abcdefg
Вы можете убедить себя, что эти 2 списка по сути одно и то же, используя, echoчтобы увидеть, к чему оболочка их расширит.
$ echo *
$ echo ./*
Эти 2 команды выведут список всех файлов в вашем текущем каталоге.
Мы можем сделать некоторые поддельные данные, например, так:
$ touch file{1..5}
$ ll
total 0
-rw-rw-r--. 1 saml saml 0 Jan 24 07:14 file1
-rw-rw-r--. 1 saml saml 0 Jan 24 07:14 file2
-rw-rw-r--. 1 saml saml 0 Jan 24 07:14 file3
-rw-rw-r--. 1 saml saml 0 Jan 24 07:14 file4
-rw-rw-r--. 1 saml saml 0 Jan 24 07:14 file5
Теперь, когда мы используем вышеупомянутые echoкоманды, мы видим следующий вывод:
$ echo *
file1 file2 file3 file4 file5
$ echo ./*
./file1 ./file2 ./file3 ./file4 ./file5
Это различие может показаться ненужным, но есть ситуации, когда вы хотите гарантировать различным инструментам командной строки Unix, что вы передаете им имена файлов через командную строку, и ничего более!
Как указывает ответ @ Stephane , из-за того, какие символы являются допустимыми при именовании файлов и каталогов в Unix, могут быть созданы опасные имена файлов, которые имеют неожиданные побочные эффекты, когда они передаются различным командам Unix в командной строке.
Очень часто использование ./будет использоваться для гарантии того, что расширенные имена файлов будут рассматриваться как имена файлов при передаче в качестве аргументов различным командам Unix.