Porque, como você diz, a entrada de file
deve ser um nome de arquivo . A saída de ls
, no entanto, é apenas texto. O fato de ser uma lista de nomes de arquivos não altera o fato de ser apenas texto e não o local dos arquivos no disco rígido.
Quando você vê a saída impressa na tela, o que vê é texto. Se esse texto é um poema ou uma lista de nomes de arquivos, não faz diferença para o computador. Tudo o que sabe é que é texto. É por isso que você pode passar a saída ls
para programas que recebem texto como entrada (embora você realmente não deva ):
$ ls / | grep etc
etc
Portanto, para usar a saída de um comando que lista nomes de arquivos como texto (como ls
ou find
) como entrada para um comando que utiliza nomes de arquivos, é necessário usar alguns truques. A ferramenta típica para isso é xargs
:
$ ls
file1 file2
$ ls | xargs wc
9 9 38 file1
5 5 20 file2
14 14 58 total
Como eu disse antes, porém, você realmente não deseja analisar a saída de ls
. Algo como find
é melhor (o que print0
imprime uma em \0
vez de uma nova coluna após cada nome de arquivo e o -0
de xargs
permite lidar com essa entrada; esse é um truque para fazer com que seus comandos funcionem com nomes de arquivos que contêm novas linhas):
$ find . -type f -print0 | xargs -0 wc
9 9 38 ./file1
5 5 20 ./file2
14 14 58 total
Que também tem sua própria maneira de fazer isso, sem a necessidade de xargs
:
$ find . -type f -exec wc {} +
9 9 38 ./file1
5 5 20 ./file2
14 14 58 total
Finalmente, você também pode usar um loop de shell. No entanto, observe que, na maioria dos casos, xargs
será muito mais rápido e mais eficiente. Por exemplo:
$ for file in *; do wc "$file"; done
9 9 38 file1
5 5 20 file2
ls
, isso indica que você deseja que todos os arquivos no diretório atual sejam tratados com ofile
comando ... Então, por que simplesmente não fazer:,file *
que responderá com uma linha para cada arquivo, pasta.