2013-09-11 3 views
11

В текущем каталоге я хотел бы напечатать в нем имя файла и его содержимое. я могу напечатать имена файлов или содержимое отдельноxargs с несколькими командами

find . | grep "file_for_print" | xargs echo 
find . | grep "file_for_print" | xargs cat 

но то, что я хочу, распечатывает их вместе, как это:

file1 
line1 inside file1 
line2 inside file1 
file2 
line1 inside file2 
line2 inside file2 

Я прочитал xargs with multiple commands as argument и попытался

find . | grep "file_for_print" | xargs -I % sh -c 'echo; cat;' 

но Безразлично» т работы. Я не знаком с xargs, поэтому не знаю, что именно означает «-I% sh -c». Может ли кто-нибудь мне помочь? Спасибо!

+0

попробовать это ..... я думаю, что это должно помочь «найти |. Grep„file_for_print“| xargs более» – nsd

ответ

14

Начнем с того, что нет практически никакой разницы между:

find . | grep "file_for_print" | xargs echo 

и

find . -name "file_for_print*" 

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

find . -name "file_for_print*" 

фактически точно так же, как

find . -name "file_for_print*" -print 

где печатает -print действий каждый согласованный имя файла с последующим переводом строки. Если вы не предоставите find с любыми действиями, предполагается, что вы хотели -print. Но у него больше трюков, чем у него. Например:

find . -name "file_for_print*" -exec cat {} \; 

В -exec причины действий найти, чтобы выполнить следующую команду до \;, заменив {} с каждым именем файла соответствия.

find не ограничивается одним действием. Вы можете сказать, что делаете, сколько хотите. Итак:

find . -name "file_for_print*" -print -exec cat {} \; 

, вероятно, сделает все, что вам нужно.

Для много дополнительной информации об этом очень полезной утилите, типа:

man find 

или

info find 

и прочитать все об этом.

+5

+1 для, возможно, наиболее мягко поставляется RTFM ;-) – necromancer

+0

да найти и xargs являются довольно удивительно. – sashang

16

find . | grep "file_for_print" | xargs -I % sh -c 'echo %; cat %;' (OP пропускал % S)

+1

Именно то, что я искал! Спасибо! – John

+0

рад помочь :-) – necromancer

0

Что о написании собственной функции оргии?

#!/bin/bash 

myFunction() { 
    while read -r file; do 
     echo "$file" 
     cat "$file" 
    done 
} 

find . -name "file_for_print*" | myFunction 
6

Поскольку он не был еще сказал: -I % говорит xargs заменить «%» с аргументами в команде вы даете ему. sh -c '...' просто означает выполнение команд '...' в новой оболочке.

Так

xargs -I % sh -c 'echo %; cat %;' 

будет работать echo [filename] с последующим cat [filename] для каждого файла данного в xargs. Команды echo и cat будут выполняться внутри другого процесса оболочки, но это обычно не имеет значения. Ваша версия не работает, потому что в ней не было указателей % внутри команды, переданной в xargs.


Для чего это стоит, я хотел бы использовать эту команду, чтобы достичь того же:

find -name "*file_for_print*" | parallel 'echo {}; cat {};' 

, потому что это проще (parallel автоматически использует {} в качестве замены символа и может занять несколько команд по умолчанию).

0

В этом конкретном случае каждая команда выполняется для каждого отдельного файла в любом случае, поэтому нет смысла использовать xargs. Вы можете просто добавить -exec дважды в ваш «найти»:

find . -name "*file_for_print*" -exec echo {} \; -exec cat {} \; 

В этом случае -print может быть использован вместо первого echo как указывал RICi, но этот пример показывает способность выполнять две произвольные команды с один find

Смежные вопросы