В терминале Unix, если я делаю:
egrep "Stuff" $(ls *.txt)
Результат очевиден. Но что делает
$(ls *.txt)
самостоятельно? Я вижу, что могу копировать эффект
egrep "Stuff" *.txt
Таким образом, что $(ls *.txt)
?
$( )
выполнения команда ls *.txt
и возвраты STDOUT
из команды.
то, Каково это конкретное использование, является новичком, программирующим ошибку по крайней мере на трех уровнях:
egrep 'Stuff' *.txt
работы, как Вы сказали, за исключением файлов, названных чем-то как A File.txt
ls
, вывод для входных данных программы неблагоразумен. См. , причины $( ls *.txt)
не справляются с именами файлов с пробелами и другими забавными символами. find . -maxdepth 1 -type f -iname '*.txt' -print0 | xargs -0 egrep 'Stuff'
более противопульный путь. А изобрел, что пример расширения/беспорядка шарика оболочки, в ответ на @8bittree:
$ /bin/ls -l -b
total 36
-rw------- 1 w3 walt 2 Aug 11 13:41 A\ \\012\ File.txt
-rw------- 1 w3 walt 2 Aug 11 13:42 A\ \n\ File.txt
-rw------- 1 w3 walt 2 Aug 11 13:40 A\ File.txt
$ grep "STUFF" $(ls *.txt)
grep: A: No such file or directory
grep: \012: No such file or directory
grep: File.txt: No such file or directory
grep: A: No such file or directory
grep: File.txt: No such file or directory
grep: A: No such file or directory
grep: File.txt: No such file or directory
$ find . -maxdepth 1 -type f -iname '*.txt' -print0 | xargs -0 egrep 'Stuff'
$ find . -maxdepth 1 -type f -iname '*.txt' -print0 | xargs -0 egrep '1'
./A File.txt:1
Ничего себе, на мгновение я думал, что Вы задавались вопросом приблизительно `$(ls *.txt)`
(с $(..)
плюс одинарные левые кавычки)
, Поскольку на вопрос уже ответили, я просто буду предупреждать Вас об одной вещи. Вот последовательность команд, чтобы показать Вам, почему это может быть опасно:
set -x
touch 'rm -f *.txt'
`$(ls *.txt)`
ls *.txt
будет выполнена, затем перенаправит результат к STDOUT. Этот результат, rm -f *.txt
будет теперь выполняться из-за одинарных левых кавычек. rm -f *.txt
я надеюсь, что Вы понимаете, - поскольку демонстрация просто выполняет предыдущие команды в пустом каталоге, таким образом, Вы ничего не повредите.
$( ... )
замена команды, она присваивает вывод одной или нескольких команд как вход к другой команде. Старый синтаксис: ` ... `
.
другое - то, что Ваши команды будут выполнены в различных оболочках:
echo $BASHPID $( echo $BASHPID )
5718 7138
Это на самом деле вызывает подоболочку:
echo $BASH_SUBSHELL $( echo $BASH_SUBSHELL )
0 1
Этот вопрос, кажется, имеет мало утилиты в реальном мире, но,
А лучший способ получить применимый результат:
echo $(ls *.txt)
Или всего
ls *.txt
Это перечислит все файлы с .txt расширением. Для нахождения текстовых файлов, которые содержат конкретную строку,
egrep -l "Stuff" *.txt
Для получения дополнительной информации о средствах поиска, делают
man egrep
"что делает $(ls *.txt)
сделайте"
$(ls *.txt)
собирает список имен файлов и затем искажает их. Не используйте это.
ls
предназначается для человекочитаемого вывода. Поскольку один из специалистов по обслуживанию ls записал в ответ на почему ls
не предложил бы a --null
опция:
Если бы мы должны были сделать это затем, это - интерфейс, который мы использовали бы. Однако
ls
действительно инструмент для прямого потребления человеком, и в этом случае последующая обработка менее полезна. Для дальнейшей обработки,find
(1) больше подходит. [акцент, добавленный]
Другими словами, использование ls
поскольку что-либо кроме дисплея людям просто не поддерживается. ls
специалисты по обслуживанию, например, недавно изменили выходной формат по умолчанию на что-то они, хотя более человечески-благоприятный без предупреждения. Так, последуйте их совету: если Вы собираетесь сделать последующую обработку имен файлов, использовать find
вместо ls
.
$(...)
замена команды. Одно последствие использования замены команды - то, что удалены запаздывающие символы новой строки. Если последнее имя файла в списке, окажется, будет содержать запаздывание новых строк, то они будут удалены.
С тех пор $(...)
не дважды заключается в кавычки, текст это, продукты подвергнутся:
Разделение Word
Расширение пути
Результат обоих из них далее искажает имен файлов.
не говоря уже о проблемах с именами файлов, запускающимися с -
из-за пропавших без вести --
(для обоих ls
и egrep
как Ubuntu egrep
быть реализацией GNU принимает опции даже после аргументов неопции если POSIXLY_CORRECT
находится в среде).
также, если любой из тех txt
файлы имели каталог типа, ls
перечислил бы их содержание вместо себя.
и если существует нет txt
файлы, вывод ls
будет пусто (хотя Вы будете видеть ошибку об отсутствии *.txt
файл) и как egrep
не получит аргумента файла, это будет искать Материал в своем стандартном входе (и по-видимому зависать).
Давайте создадим 4 файла, содержащие Stuff
в нашем каталоге:
$ echo Stuff | tee file1 file2 'a b c.txt' 'f* .txt'
Stuff
$ ls -Q
"a b c.txt" "file1" "file2" "f* .txt"
Теперь, давайте выполним команду egrep:
$ egrep "Stuff" $(ls *.txt)
grep: a: No such file or directory
grep: b: No such file or directory
grep: c.txt: No such file or directory
file1:Stuff
file2:Stuff
f* .txt:Stuff
grep: .txt: No such file or directory
Заметьте, что мы получаем 4 сообщения об ошибках о несуществующих файлах. Это происходит из-за разделения слова. Результат также показывает соответствия с двумя файлами, file1
и file2
это не должно было искаться, потому что они не заканчивают .txt
. Это из-за _pathname расширения'.
Правильно записанная команда производит два успешных соответствия и никакие ошибки:
$ egrep -- "Stuff" *.txt
a b c.txt:Stuff
f* .txt:Stuff
Использование:
egrep -- "Stuff" *.txt
или POSIXly:
grep -E -- "Stuff" *.txt
или:
grep -E -e Stuff -- *.txt
Это будет работать с любым именем файла и не имеет ни одного из ограничений ls
подход.