Intereting Posts
Указание сетевого интерфейса для диска cifs (samba) realmd присоединяется к AD и Cross Domain Auth Как сделать загрузочную полную резервную копию корневого сервера Debian на облачный накопитель i915 не может работать с nomodeset? Как включить IOMMU на Gigabyte 990FXA-UD5 R5 zsh-completion: Завершение двух частей аргумента, разделенных двоеточием Как создать сводку отчетов о сообщениях, которые вызвали конкретный код DSN .bashrc загружен в оболочку входа Как я могу заставить пользователя войти в систему с помощью ключей ssh, но не с паролем? Захват веб-трафика, сгруппированный отдельными потоками TCP Вставьте новые строки с помощью vim Когда я использую ожидаемый модуль ansible, я получаю следующее сообщение: требуется модуль pexpect pexpect Couting всех символов с помощью класса символов BASH Что вы делаете в баш-шебанге? ошибка, возникающая при использовании su -c: bash: без контроля заданий в этой оболочке

Преобразование рабочей команды в файл сценария оболочки, который получает аргументы

Привет, моя рабочая команда:

grep -l "my text" file*.ext|xargs ls -lart 

эта команда очень полезна для меня, и я хотел создать файл оболочки, который делает это с меньшим набором текста, например так:

 fn "my text" file*.ext 

Я пришел к этому файлу сценария оболочки:

 grep -l "$1" "$2"|xargs ls -lart 

который не работает, даже первая часть не работает:

 grep -l "$1" "$2" 

который возвращает ноль

Ваш сценарий должен принимать более двух аргументов.

Перед тем, как shell выполняет команду 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 мы избегаем возможных недоразумений, если файлы типа directory совпадают.

С -r мы избегаем enums текущего каталога, если нет соответствующего файла.

Обратите внимание, что для большого количества файлов xargs может выбрать запуск более одного вызова ls с частью списка файлов, что означает, что вывод не будет должным образом перечислен по времени.

Также обратите внимание, что - означает stdin для grep , но файл называется - в текущем каталоге для ls . GNU grep -l выведет (standard input) (или его перевод на вашем языке). Если вы хотите указать файл с именем - в текущем каталоге, используйте ./- вместо - .