Что делает $ (ls *.txt), делают?

В терминале Unix, если я делаю:

egrep "Stuff" $(ls *.txt)

Результат очевиден. Но что делает

$(ls *.txt) самостоятельно? Я вижу, что могу копировать эффект

egrep "Stuff" *.txt

Таким образом, что $(ls *.txt)?

5
задан 10 August 2017 в 01:17

5 ответов

$( ) выполнения команда ls *.txt и возвраты STDOUT из команды.

то, Каково это конкретное использование, является новичком, программирующим ошибку по крайней мере на трех уровнях:

  1. egrep 'Stuff' *.txt работы, как Вы сказали, за исключением файлов, названных чем-то как A File.txt
  2. Используя ls, вывод для входных данных программы неблагоразумен. См. , причины
  3. $( 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
6
ответ дан 23 November 2019 в 08:35

Ничего себе, на мгновение я думал, что Вы задавались вопросом приблизительно `$(ls *.txt)`$(..) плюс одинарные левые кавычки)

, Поскольку на вопрос уже ответили, я просто буду предупреждать Вас об одной вещи. Вот последовательность команд, чтобы показать Вам, почему это может быть опасно:

  • set -x
    Для наблюдения, что выполняется
  • touch 'rm -f *.txt'
    , Создают текстовый файл, названный 'комната-f *.txt', я использую простые кавычки здесь, таким образом, Bash не развернет подстановочный знак и пробелы.
  • `$(ls *.txt)`
    Вот хитрая часть. Команда ls *.txt будет выполнена, затем перенаправит результат к STDOUT. Этот результат, rm -f *.txt будет теперь выполняться из-за одинарных левых кавычек.
    Так, комната удалит каждый текстовые файлы, в нашем случае файл rm -f *.txt

я надеюсь, что Вы понимаете, - поскольку демонстрация просто выполняет предыдущие команды в пустом каталоге, таким образом, Вы ничего не повредите.

3
ответ дан 23 November 2019 в 08:35
$( ... )

замена команды, она присваивает вывод одной или нескольких команд как вход к другой команде. Старый синтаксис: ` ... `.

другое - то, что Ваши команды будут выполнены в различных оболочках:

echo $BASHPID $( echo $BASHPID )
5718 7138

Это на самом деле вызывает подоболочку:

echo $BASH_SUBSHELL $( echo $BASH_SUBSHELL )
0 1
2
ответ дан 23 November 2019 в 08:35

Этот вопрос, кажется, имеет мало утилиты в реальном мире, но,

А лучший способ получить применимый результат:

echo $(ls *.txt)

Или всего

ls *.txt

Это перечислит все файлы с .txt расширением. Для нахождения текстовых файлов, которые содержат конкретную строку,

egrep -l "Stuff" *.txt

Для получения дополнительной информации о средствах поиска, делают

man egrep
0
ответ дан 23 November 2019 в 08:35

"что делает $(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 подход.

28
ответ дан 23 November 2019 в 08:35

Другие вопросы по тегам:

Похожие вопросы: