Вы подошли близко.
Перед выборочной печатью строк необходимо подавить вывод sed
:
$ cal 12 2015 | sed -n '3,7p'
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Ваш sed
может не иметь -n
. В этом случае используйте d
, чтобы удалить все строки, кроме тех, которые вам нужны.
Ваша команда tr
заменяет все, кроме букв, включая цифры. Просто замените пробелы:
$ cal 12 2015 | sed -n '3,7p' | tr -s '' '\ n'
1
2
3
4
5
6
7
8
9
10
11
12
Ваш сценарий должен принимать более двух аргументов.
Прежде чем оболочка выполнит grep
в команде
grep -l "my text" file*.ext
шаблон подстановки имен файлов file*.ext
расширяется до всех совпадающих имен файлов. Таким образом, командная строка, которая будет запущена в конце, будет
grep -l "my text" file1.ext file2.ext file3.ext
(если это файлы, соответствующие шаблону)
Таким образом, ваш скрипт может выглядеть так
#!/bin/sh
pattern=$1
shift
grep -l -e "$pattern" "$@" | xargs ls -lrt
Здесь шаблон сохраняется в переменной, а затем удаляется из списка аргументов командной строки. Остальные аргументы представляют собой список имен файлов (, если шаблон подстановки имен файлов в командной строке соответствует )и доступен в "$@"
.
Убедитесь, что вы используете двойные кавычки $@
. Это приведет к тому, что $@
расширится до списка отдельно цитируемых аргументов командной строки.
Я удалил параметр -a
из ls
, так как он не нужен при указании явных имен файлов в список. Я также использую grep
с -e
для указания шаблона, так как шаблон с начальным дефисом(-
)в противном случае может сбить с толку grep
.
Если бы не сортировка, я бы предложил следующую find
команду вместо вашего пайплайна (правильно обрабатывает имена файлов с пробелами и символами новой строки):
find. -type f -name "$filepattern" -exec grep -q -e "$pattern" {} ';' -ls
Это ищет файлы с именами, соответствующими тому, что находится в $filepattern
, и с содержимым, соответствующим тому, что находится в $pattern
, а затем производит ls -l
-, как вывод. Поиск выполняется рекурсивно в текущем каталоге.
Как часть скрипта:
#!/bin/sh
pattern=$1
filepattern=$2
find. -type f -name "$filepattern" -exec grep -q -e "$pattern" {} ';' -ls
Этот скрипт необходимо вызывать таким образом, чтобы шаблон подстановки имени файла не расширялся оболочкой при его вызове:
$./script.sh 'my text' 'file*.ext'
Чтобы сделать его немного безопаснее, но полагаясь на расширения GNU:
#! /bin/sh -
pattern=${1?pattern required}; shift
: "${1?no filename specified}"
grep -l --null -e "$pattern" -- "$@" |
xargs -r0 ls -lrtd --
С помощью --null
/ -0
мы избегаем проблем с именами файлов, которые содержат пробелы, кавычки или обратную косую черту.
Используя -e "$pattern"
, мы избегаем проблем с шаблонами, начинающимися с -
.
Используя --
, мы избегаем проблем с именами файлов, начинающимися с -
.
С помощью -d
мы избегаем возможных недоразумений, если файлы типа каталог совпадают.
С помощью -r
мы избегаем перечисления текущего каталога, если нет соответствующего файла.
Обратите внимание, что для большого количества файлов xargs
может быть выбрано выполнение более одного ls
вызова с частью списка файлов, что означает, что выходные данные не будут должным образом перечислены по времени.
Также обратите внимание, что -
будет означать stdin для grep
, но файл с именем -
в текущем каталоге для ls
. GNU grep -l
выведет(standard input)
(или его перевод на ваш язык ). Если вы хотите указать файл с именем -
в текущем каталоге, используйте ./-
вместо -
.