Согласно моему пониманию, подстановочный знак шарика интерпретируется оболочкой, которая затем выполняет данную команду для каждого имени файла соответствия. Предположим, что у меня есть файлы: abc1, abc2, and abc3
в моем текущем каталоге. Затем например, echo abc*
отзовется эхом однажды для каждого имени файла, запускающегося с 'abc'.
Однако, если я работаю grep 'foo' abc*
, Я предполагаю, что это должно работать:
grep 'foo' abc1
grep 'foo' abc2
grep 'foo' abc3
Что означает, что я должен получить следующий вывод (предполагающий, что все файлы содержат одну строку, которая говорит 'нечто'):
foo
foo
foo
Однако вместо этого я добираюсь:
abc1:foo
abc2:foo
abc3:foo
Таким образом, я полагаю, что существует 2 возможных объяснения этого. Во-первых, так или иначе grep, может обнаружить, что это использовалось с шариком выражения и отвечает путем вывода имен файлов перед соответствиями. Во-вторых, так как можно передать несколько файлов grep, оболочка на самом деле выполняет только 1 команду:
grep 'foo' abc1 abc2 abc3
Однако это только работает, потому что grep принимает несколько файлов в конце. Возможно, что другая команда только позволила бы 1 файлу быть переданным в. Таким образом, если бы Вы хотели выполнить команду для нескольких файлов, соответствующих шарику, то она не работала бы, если бы globbing работал с помощью второго метода, описанного выше.
Так или иначе кто-то может пролить некоторый свет на это?
Спасибо!
Это - прием: команда не знает, это - оболочка, которая делает задание
Рассмотрите, например, grep 'abc' *.txt
. Если мы выполним трассировку системных вызовов, то Вы будете видеть что-то вроде этого:
bash-4.3$ strace -e trace=execve grep "abc" *.txt > /dev/null
execve("/bin/grep", ["grep", "abc", "ADDA_converters.txt", "after.txt", "altera_license.txt", "altera.txt", "ANALOG_DIGITAL_NOTES.txt", "androiddev.txt", "answer2.txt", "answer.txt", "ANSWER.txt", "ascii.txt", "askubuntu-profile.txt", "AskUbuntu_Translators.txt", "a.txt", "bash_result.txt", ...], [/* 80 vars */]) = 0
+++ exited with 0 +++
Оболочка расширена *.txt
во все имена файлов в текущем каталоге тот конец с .txt
расширение. Так эффективно Ваша оболочка переводит grep 'abc' *.txt
команда в grep 'abc' file1.txt file2.txt file3.txt . . .
. Таким образом Ваше второе предположение корректно.
Первое предположение не корректно - программы не имеют никакого способа обнаружить шарик. Возможно передать *
как аргумент строки для управления но это - задание команды для решения, что сделать с ним затем. Расширение имени файла, однако, является свойством Вашей соответствующей оболочки, как я уже упомянул.
Однако это только работает, потому что grep принимает несколько файлов в конце. Возможно, что другая команда только позволила бы 1 файлу быть переданным в.
Точно правильный! Программы не ограничивают количество приемлемых параметров командной строки (например, в C это - массив строк const char *args[]
и в Python sys.argv[]
), но они могут обнаружить длину того массива или является ли что-то неожиданное в неправильном положении массива. grep
не делает этого и принимает несколько файлов, который является дизайном.
На ноте стороны неподходящее заключение в кавычки вместе с globbing с grep может иногда быть проблемой. Рассмотрите это:
bash-4.3$ echo "one two" | strace -e trace=execve grep *est*
execve("/bin/grep", ["grep", "self_test.sh", "test.wxg"], [/* 80 vars */]) = 0
+++ exited with 1 +++
Неприготовленный пользователь ожидал бы, что grep будет соответствовать любой строке est
буквы в нем прибывающий из канала, но вместо этого расширения имени файла оболочки скрутили все вокруг. Я видел, что это происходит много с людьми, которые делают ps aux | grep shell_script_name.sh
, и они ожидают находить свое выполнение процесса, но потому что они выполнили команду из того же каталога, где сценарий был, сделанное расширение имени файла оболочки grep
управляйте для взгляда полностью отличающимися негласно от того, что ожидал пользователь.
Надлежащий путь состоял бы в том, чтобы использовать одинарные кавычки:
bash-4.3$ echo "one two" | strace -e trace=execve grep '*est*'
execve("/bin/grep", ["grep", "*est*"], [/* 80 vars */]) = 0
+++ exited with 1 +++