Estou fazendo um find
e, em seguida, obtendo uma lista de arquivos. Como canalizá-lo para outro utilitário como cat
(para que o gato exiba o conteúdo de todos esses arquivos) e basicamente precise de grep
algo desses arquivos.
Estou fazendo um find
e, em seguida, obtendo uma lista de arquivos. Como canalizá-lo para outro utilitário como cat
(para que o gato exiba o conteúdo de todos esses arquivos) e basicamente precise de grep
algo desses arquivos.
Respostas:
Canalização para outro processo (embora isso NÃO realize o que você disse que está tentando fazer):
command1 | command2
Isso enviará a saída do comando1 como a entrada do comando2
-exec
em um find
(isso fará o que você deseja fazer - mas é específico find
)
find . -name '*.foo' -exec cat {} \;
(Tudo entre find
e -exec
os predicados de localização que você já estava usando. {}
Substituirá o arquivo específico que você encontrou no comando ( cat {}
nesse caso); \;
é para finalizar o -exec
comando.)
envia a saída de um processo como argumentos de linha de comando para outro processo
command2 `command1`
por exemplo:
cat `find . -name '*.foo' -print`
(Observe que estas não são aspas regulares (sob o til ~ do meu teclado).) Isso enviará a saída de command1
para command2
argumentos de linha de comando. Observe que os nomes de arquivos que contêm espaços (novas linhas, etc) serão divididos em argumentos separados.
find
permitem escrever:, find . -name '*.foo' -exec cat {} +
onde +
indica que find
deve agrupar quantos nomes de arquivos forem convenientes em uma única chamada de comando. Isso é bastante útil (lida com espaços etc. nos nomes de arquivos sem recorrer a -print0
e xargs -0
).
find . -name '*.foo' | xargs cat
find . -name '*.foo' | xargs cat | grep string
O POSIX 2008 adicionou o +
marcador, o find
que significa que agora agrupa automaticamente quantos arquivos forem razoáveis em uma única execução de comando, muito parecido com o xargs
faz, mas com várias vantagens:
O problema do nome do arquivo é um problema xargs
sem a -0
opção e o problema 'executar mesmo com zero nome de arquivo' é um problema com ou sem a -0
opção - mas o GNU xargs
tem a opção -r
ou --no-run-if-empty
para impedir que isso aconteça. Além disso, essa notação reduz o número de processos, não é provável que você avalie a diferença de desempenho. Portanto, você poderia escrever sensatamente:
find . -exec grep something {} +
find . -print | xargs grep something
Se você estiver no Linux ou tiver o GNU find
e os xargs
comandos, use -print0
com find
e -0
com xargs
para manipular nomes de arquivos que contenham espaços e outros caracteres estranhos.
find . -print0 | xargs -0 grep something
grep
Se você não quiser os nomes dos arquivos (apenas o texto), adicione uma opção apropriada para grep
(geralmente -h
para suprimir 'títulos'). Para garantir absolutamente que o nome do arquivo seja impresso grep
(mesmo que apenas um arquivo seja encontrado ou a última chamada de grep
tenha apenas um nome de arquivo), adicione /dev/null
-o à xargs
linha de comando, para que sempre haja pelo menos dois nomes de arquivo.
xargs grep something
.
find
é canalizada para a entrada padrão de xargs
. O xargs
programa lê sua entrada padrão, dividindo a entrada em espaço em branco (espaços em branco, novas linhas, guias, etc) e anexa várias palavras ao comando grep something
e executa a linha de comando. xargs
em seguida, continua lendo a entrada e executando comandos até ficar sem entrada. xargs
executa o grep
comando quantas vezes for necessário para a entrada que é fornecida ( find
neste exemplo).
/dev/null
perde as mensagens de erro.
Existem algumas maneiras de passar a lista de arquivos retornados pelo find
comando para o cat
comando, embora tecnicamente nem todos usem canalização, e nenhum deles seja canalizado diretamente cat
.
O mais simples é usar backticks ( `
):
cat `find [whatever]`
Isso pega a saída find
e efetivamente a coloca na linha de comando de cat
. Isso não funciona bem se find
houver muita saída (mais do que pode caber em uma linha de comando) ou se a saída tiver caracteres especiais (como espaços).
Em algumas conchas, inclusive bash
, pode-se usar em $()
vez de reticulares:
cat $(find [whatever])
Isso é menos portátil, mas é aninhado. Além disso, tem praticamente as mesmas ressalvas que os backticks.
Como a execução de outros comandos no que foi encontrado é de uso comum find
, o find possui uma -exec
ação que executa um comando para cada arquivo encontrado:
find [whatever] -exec cat {} \;
O {}
é um espaço reservado para o nome do arquivo e \;
marca o final do comando (é possível executar outras ações depois -exec
.)
Isso será executado cat
uma vez para cada arquivo, em vez de executar uma única instância, cat
transmitindo vários nomes de arquivos que podem ser ineficientes e podem não ter o comportamento desejado para alguns comandos (embora seja bom cat
). A sintaxe também é difícil de digitar - você precisa escapar do ponto e vírgula porque o ponto e vírgula é especial para o shell!
Algumas versões find
(principalmente a versão GNU) permitem substituir ;
por+
a utilização -exec
do modo de acréscimo para correr menos casos de cat
:
find [whatever] -exec cat {} +
Isso passará vários nomes de arquivos para cada chamada de cat
, o que pode ser mais eficiente.
Observe que isso não garante que você use uma única chamada, no entanto. Se a linha de comando for muito longa, os argumentos serão espalhados por várias invocações decat
. Pois cat
isso provavelmente não é grande coisa, mas para alguns outros comandos isso pode mudar o comportamento de maneiras indesejáveis. Nos sistemas Linux, o limite de comprimento da linha de comando é bastante grande, portanto, a divisão em várias invocações é bastante rara em comparação com outros sistemas operacionais.
A abordagem clássica / portátil é usar xargs
:
find [whatever] | xargs cat
xargs
executa o comando especificado ( cat
neste caso) e adiciona argumentos com base no que lê do stdin. Assim como -exec
com +
, isso vai quebrar a linha de comando, se necessário. Ou seja, se find
produzir muita saída, ele será executado cat
várias vezes. Conforme mencionado na seção -exec
anterior, existem alguns comandos em que essa divisão pode resultar em um comportamento diferente. Observe que usarxargs
dessa maneira apresenta problemas com espaços nos nomes de arquivos, pois xargs
apenas usa espaços em branco como delimitador.
O método mais robusto, portátil e eficiente também usa xargs
:
find [whatever] -print0 | xargs -0 cat
O -print0
sinalizador indica find
para usar \0
delimitadores (caracteres nulos) entre os nomes de arquivos, e o -0
sinalizador informa xargs
para esperar esses \0
delimitadores. Isso tem um comportamento praticamente idêntico ao da abordagem -exec
... +
, embora seja mais portátil (mas infelizmente mais detalhado).
ls
.
$()
Também funciona com comandos diferentes de find
.
Parece um trabalho para um script de shell para mim:
for file in 'find -name *.xml'
do
grep 'hello' file
done
ou algo assim
O comando find possui um argumento -exec que você pode usar para coisas como essa; você pode fazer o grep diretamente usando isso.
Por exemplo ( daqui, outros bons exemplos nesta página ):
find . -exec grep "www.athabasca" '{}' \; -print
No bash, o seguinte seria apropriado:
find /dir -type f -print0 | xargs -0i cat {} | grep whatever
Isso localizará todos os arquivos no /dir
diretório e canalizará com segurança os nomes de arquivos xargs
, os quais serão conduzidos com segurança grep
.
Ignorar xargs
não é uma boa ideia se você tiver muitos milhares de arquivos /dir
; cat
será interrompido devido ao tamanho excessivo da lista de argumentos. xargs
vai resolver tudo isso para você.
O -print0
argumento find
mescla com o -0
argumento xargs
para manipular nomes de arquivos com espaços corretamente. O -i
argumento para xargs
permite inserir o nome do arquivo quando necessário na cat
linha de comando. Os colchetes são substituídos pelo nome do arquivo canalizado no cat
comando de find
.
Isso funciona para mim
find _CACHE_* | while read line; do
cat "$line" | grep "something"
done
Use ggrep .
ggrep -H -R -I "mysearchstring" *
para procurar um arquivo no unix contendo texto localizado no diretório atual ou em um subdiretório
Isso imprimirá o nome e o conteúdo dos arquivos somente recursivamente.
find . -type f -printf '\n\n%p:\n' -exec cat {} \;
Editar (versão aprimorada): imprime o nome e o conteúdo dos arquivos de texto (ascii) somente recursivamente.
find . -type f -exec grep -Iq . {} \; -print | xargs awk 'FNR==1{print FILENAME ":" $0; }'
Mais uma tentativa
find . -type f -exec grep -Iq . {} \; -printf "\n%p:" -exec cat {} \;
Você está tentando encontrar texto nos arquivos? Você pode simplesmente usar grep para isso ...
grep searchterm *
Para listar e ver o conteúdo de todos os arquivos abc.def em um servidor nos diretórios / ghi e / jkl
find /ghi /jkl -type f -name abc.def 2> /dev/null -exec ls {} \; -exec cat {} \;
Para listar os arquivos abc.def que comentaram entradas e exibem, consulte essas entradas nos diretórios / ghi e / jkl
find /ghi /jkl -type f -name abc.def 2> /dev/null -exec grep -H ^# {} \;
find -name '*.foo' -print
trabalhou muito para mim ... Obrigado