arquivo $ (ls / usr / bin / * | grep zip) comando me dá erros. O que há de errado?

4

Eu decidi ler um livro sobre Linux / Unix. Eu cheguei a um capítulo onde eles tentam explicar como passar a saída de comandos como expansões para o shell.

O seguinte comando

file $(ls /usr/bin/* | grep zip)

me dá o erro "não pode abrir" o nome do arquivo (Nenhum arquivo ou diretório) ". Pelo contrário, quando eu faço

file $(ls | grep zip)

tudo aparece normalmente, não importa a pasta. Por quê? É algum tipo de restrição de argumento?

Se eu fizer isso

file $(ls Pictures/ | grep jpg)

Eu recebo o seguinte:

1234.jpg: ERROR: cannot open 1234.jpg (No such file or directory)

ao mover-se para a direita no diretório que desejo listar

nassosdim@ubuntu:~$ cd Pictures/

nassosdim@ubuntu:~/Pictures$ file $(ls | grep jpg)

imprime o resultado do arquivo

1234.jpg: JPEG image data, JFIF standard 1.01

Alguém pode me explicar o que está acontecendo? : (

    
por Nassosdim 30.07.2011 / 21:54

4 respostas

6

O erro está chegando porque o bash está tentando expandir o * em seu argumento para ls usando a correspondência de padrões glob. Será sempre através de tal erro quando a glob não corresponder ao padrão. O * , em seguida, é passado para ls como um asterisco real, que não corresponde a um arquivo, portanto ls resultará em erro!

Existem vários bits sobre o que você está fazendo que são redundantes. Eu sei que você está tentando aprender um constructo, mas vamos dividir alguns dos pedaços do que você acabou de realizar e como isso poderia ter sido feito.

  1. ls /usr/bin é suficiente para listar arquivos no diretório bin, você não precisa da estrela.
  2. Você nunca deve analisar a saída de ls , é ambíguo e potencialmente perigoso.
  3. Você pode obter o mesmo efeito sem o grep fazendo ls /usr/bin/*zip* , mas o ls ainda é redundante, você pode simplesmente passar o expantion glob para o arquivo: file /usr/bin/*zip*

Por fim, find geralmente é uma ferramenta melhor para localizar arquivos. Você poderia fazer o que você está assim:

$ find /usr/bin -iname '*zip*' -exec file {} +
    
por 30.07.2011 / 22:10
1

O shell expande o * e transforma o comando em file $(ls /usr/bin/a /usr/bin/b /usr/bin/whatever | grep zip) . Você não precisa especificar um asterisco no UNIX, a menos que você queira que o shell o expanda para incluir tudo antes de passá-lo para o ls .

i.e. seu shell substitui o * por todos os arquivos correspondentes antes ele executa o comando, que não é como ele funciona no Windows se você estiver acostumado com isso.

Leia a seção 3.4.9 aqui .

file $(ls /usr/bin/ | grep zip) 

é o caminho certo para fazê-lo (no sentido de que você não precisa do *, mas veja a resposta do Caleb para outras questões e opções). Mas note que isso realmente é executado,

file /usr/bin/a /usr/bin/b /usr/bin/whatever

não

file /usr/bin/a
file /usr/bin/b
file /usr/bin/whatever

novamente, não funciona da maneira que o Windows faz.

    
por 30.07.2011 / 22:07
1

Por favor, tente ls /usr/bin/* | grep zip para ver quais argumentos você está alimentando para file . Fiquei perplexo com o resultado um pouco. No meu sistema Ubuntu, o resultado é este:

/usr/bin/funzip
/usr/bin/gpg-zip
/usr/bin/mzip
/usr/bin/preunzip
/usr/bin/prezip
/usr/bin/prezip-bin
/usr/bin/unzip
/usr/bin/unzipsfx
/usr/bin/zip
/usr/bin/zipcloak
/usr/bin/zipgrep
/usr/bin/zipinfo
/usr/bin/zipnote
/usr/bin/zipsplit
funzip
gpg-zip
mzip
preunzip
prezip
prezip-bin
unzip
unzipsfx
zip
zipcloak
zipgrep
zipinfo
zipnote
zipsplit

Usando ls /usr/bin/* | less , podemos ver porque obtemos esse resultado: depois de todos os arquivos em / usr / bin, ls também lista o conteúdo do diretório / usr / bin / X11, e os lista sem o diretório nomes prefixados.

E quando você alimenta esses nomes de arquivos sem um nome de diretório para file , file não pode encontrar esses arquivos e você recebe as mensagens de erro "Não há arquivo ou diretório" (como uma observação: se você receber mensagens de erro , por favor, não diga apenas "recebi erros", mas publique as mensagens de erro.

Como o Caleb já postou, use apenas file /usr/bin/*zip* .

    
por 30.07.2011 / 22:26
1

A análise dos resultados de ls pode ser um negócio arriscado, pois o formato de saída varia. Seria melhor você fazer algo assim:

file /path/to/*.zip

Tente um comando mais simples para demonstrar como a substituição do processo funciona:

ls $(echo /usr/bin) 
    
por 30.07.2011 / 22:46