Distinguir um comando e não um segundo transmissor nativo

0

suponha que

[root@iz2ze9wve43n2nyuvmsfx5z /]# find . -maxdepth 2 -type d  | ls
bin   dev  home  lib64       media  opt   root  sbin  sys  usr
boot  etc  lib   lost+found  mnt    proc  run   srv   tmp  var

Não fiz nada, como resgate eu deveria reconstruí-los para uma lista para ls

find . -type d | xargs ls
#millions of outputs

No entanto, o grep faz um bom trabalho

[root@iz2ze9wve43n2nyuvmsfx5z /]# find . -maxdepth 2 -type d  | grep home
./home

Como eu poderia distinguir um comando não nasceu como um segundo transmissor a partir de compreensão subjacente, em vez de tentar, testar erros e lembrar.

    
por JawSaw 06.11.2018 / 02:34

1 resposta

4

Você aprende e lembra o que os vários programas fazem, ou você verifica as man pages.

A descrição de ls é:

List information about the FILEs (the current directory by default)

onde FILEs se refere à sinopse:

ls [OPTION]... [FILE]...

A parte importante a ser lembrada sobre ls é que ele gerará informações sobre os "ARQUIVOS" que você der - na linha de comando . O manual não descreve as maneiras pelas quais ls lê qualquer entrada (de, por exemplo, um pipe).

Compare a página ls man com, digamos, a página cat man, que diz:

cat [OPTION]... [FILE]...

Concatenate FILE(s) to standard output. With no FILE, or when FILE is -, read standard input.

Com cat , você pode cat /some/file ou pode echo hi | cat .

Portanto, no seu primeiro exemplo,

find . -maxdepth 2 -type d  | ls

find foi e fez algum trabalho e passou alguns (ou nenhum) nome de diretório em seu stdout, que se tornou stdin de ls , que ls prontamente ignorou. Como você forneceu ls no FILEs para listar, o padrão era listar o diretório atual.

No seu segundo exemplo,

find . -type d | xargs ls

find foi e fez (mais) funcionar, produzindo todos os diretórios encontrados em seu stdout, que por sua vez foi apresentado a xargs como stdin. A man page para xargs lê, em parte:

xargs reads items from the standard input ... and executes the command one or more times ...

então ls é chamado quantas vezes forem necessárias, dado o número de linhas de entrada no stdin.

A mesma ideia se traduz em seu terceiro comando:

find . -maxdepth 2 -type d  | grep home

find passa qualquer nome de diretório para o stdin de grep ; página do homem do grep diz, novamente em parte:

grep searches the named input FILEs for lines containing a match to the given PATTERN. If no files are specified, or if the file “-” is given, grep searches standard input.

A idéia de um pipeline é simples, mas poderosa, e você simplesmente precisa saber que tipo de saída um programa produz e se um programa pode consumir a entrada em seu stdin.

grep é uma das ferramentas mais comuns para usar nessas situações. Você pode usá-lo como o comando principal:

grep some-text file1 file2 file3 ...

em cujo caso grep sabe os nomes dos arquivos, ou você pode enviá-los em sua stdin:

cat file1 file2 file3 ... | grep some-text

... neste caso, grep agora não conhece mais nenhum nome de arquivo ( cat os conhecia, então produziu seu conteúdo para stdout), e agora o grep não pode saber quais arquivos continham o texto - apenas quais linhas correspondiam. / p>

É tentador encadear um monte de comandos juntos - muitas vezes chamado de "one-liner", muitas vezes semi-facetious, como um "one-liner" pode se tornar longo o suficiente para envolver dois uma segunda linha em uma janela de terminal - - em um "pipeline". Aqui, novamente, você precisa saber exatamente como os programas estão produzindo e consumindo dados.

Dados os arquivos chamados file1 , file2 e file3 , você pode fazer algo como:

find . -name 'file*' | xargs cat

e você não ficará surpreso quando find produzir os três nomes de arquivos como stdout -

file1 
file2 
file3

... para o qual xargs compila uma lista e envia para cat -

cat file1 file2 file3

... quem vê esses três nomes de arquivos e despeja seu conteúdo em sua tela.

Cuidado, então, de um arquivo chamado "file name here"; o comando find acima será exibido:

file name here
file1
file2
file3

... para o qual xags compila uma lista para cat -

cat file name here file1 file2 file3

... ao qual cat reclama (para stderr!):

cat: file: No such file or directory

cat: name: No such file or directory

cat: here: No such file or directory

... seguido pelo conteúdo do arquivo1, arquivo2 e arquivo3.

Agora você está preparado para evitar essa situação usando find ... -exec ou alternativas como find ... -print0 | xargs -0 ... para usar NULLs como delimitadores para nomes de arquivos.

    
por 06.11.2018 / 03:45

Tags