Ответ 1
Вы можете использовать xargs
:
grep 'pattern' input | xargs -I% cp "%" "%.bac"
Я хочу передать каждый вывод из команды в виде нескольких аргументов во вторую команду, например:
grep "pattern" input
возвращает:
file1
file2
file3
и я хочу скопировать эти выходы, например:
cp file1 file1.bac
cp file2 file2.bac
cp file3 file3.bac
Как я могу это сделать за один раз? Что-то вроде:
grep "pattern" input | cp $1 $1.bac
Вы можете использовать xargs
:
grep 'pattern' input | xargs -I% cp "%" "%.bac"
Вы можете использовать $()
для интерполяции вывода команды. Таким образом, вы можете использовать kill -9 $(grep -hP '^\d+$' $(ls -lad /dir/*/pid | grep -P '/dir/\d+/pid' | awk '{ print $9 }'))
, если хотите.
В дополнение к Хорошему ответу Криса Джет-Янга, я бы сказал, что xargs
также является хорошим решением для этих ситуаций:
grep ... `ls -lad ... | awk '{ print $9 }'` | xargs kill -9
сделает это. Все вместе:
grep -hP '^\d+$' `ls -lad /dir/*/pid | grep -P '/dir/\d+/pid' | awk '{ print $9 }'` | xargs kill -9
Для полноты я также упомянул подстановку команд и объясню, почему это не рекомендуется:
cp $(grep -l "pattern" ) каталог/
Код>
(Синтаксис backtick cp `grep -l "pattern" input` directory/
примерно эквивалентен, но он устарел и громоздкий, не используйте его.)
Это не удастся, если вывод из grep
создает имя файла, содержащее пробел или метасимвол оболочки.
Конечно, это хорошо, если вы точно знаете, какие имена файлов grep
могут произвести, и проверили, что ни одна из них не является проблематичной. Но для сценария производства не используйте это.
В любом случае, для сценария OP, где вам нужно отдельно относиться к каждому соответствию и добавлять к нему расширение, альтернативы xargs
или при чтении
в любом случае превосходны.
В худшем случае (имея в виду проблемные или неуказанные имена файлов) передайте совпадения в подоболочку через xargs
:
grep -l "pattern" input |
xargs -r sh -c 'для f; do cp "$ f" "$ f.bac"; сделанный' _
Код>
... где очевидно, что script внутри цикла для
может быть сколь угодно сложным.
В идеальном случае команда, которую вы хотите запустить, проста (или универсальна) достаточно, чтобы вы могли просто передать ей произвольно длинный список имен файлов. Например, GNU cp
имеет параметр -t
, чтобы облегчить это использование xargs
(опция -t
вам следует поместить в командной строке целевой каталог first, поэтому вы можете поместить столько файлов, сколько хотите в конце команды):
grep -l "pattern" input | xargs cp -t destdir
Код>
который будет расширяться в
cp -t destdir file1 file2 file3 file4...
Код>
для количества совпадений, таких как xargs
, может вписываться в командную строку cp
, повторяется столько раз, сколько требуется, чтобы передать все файлы в cpкод > . (К сожалению, это не соответствует сценарию OP, если вам нужно переименовать каждый файл во время копирования, вам нужно передать всего два аргумента за вызов
cp
: имя исходного файла и имя целевого файла чтобы скопировать его.)
Иными словами, если вы используете синтаксис подстановки команд и grep
создает длинный список совпадений really, вы рискуете столкнуться с ARG_MAX
и слишком длинный список "Аргумент списка"; но xargs
будет специально избегать этого, вместо этого копируя только столько аргументов, сколько он может безопасно перейти к cp
за раз и запустить cp
несколько раз при необходимости.