Por que é preferível `sort <" $ f1 "` em vez de `sort -" $ f1 "`, e por que isso é preferido em vez de `sort" $ f1 "`?

29

De /unix//a/458074/674

Lembre-se de usar -- ao passar argumentos arbitrários para comandos (ou use redirecionamentos sempre que possível). Então, sort -- "$f1"ou melhor, em sort < "$f1"vez de sort "$f1".

Por que é preferível usar --e redirecionar?

Por que é sort < "$f1"preferível sort -- "$f1"?

Por que é sort -- "$f1"preferível sort "$f1"?

Obrigado.

Tim
fonte
Similar: Quando devo usar o redirecionamento de entrada?
Stéphane Chazelas 7/11

Respostas:

55
sort "$f1"

falha nos valores $f1que começam com -ou aqui, no caso de sortalguns que começam com +(podem ter graves consequências para um arquivo chamado, -o/etc/passwdpor exemplo).

sort -- "$f1"

(em que -- sinaliza o final das opções) soluciona a maioria desses problemas, mas ainda falha no arquivo chamado -(que sortinterpreta como significando seu stdin).

sort < "$f1"

Não tem esses problemas.

Aqui, é o shell que abre o arquivo. Isso também significa que, se o arquivo não puder ser aberto, você também receberá uma mensagem de erro potencialmente mais útil (por exemplo, a maioria dos shells indicará o número da linha no script) e a mensagem de erro será consistente se você usar redirecionamentos sempre que possível para abrir arquivos.

E em

sort < "$f1" > out

(ao contrário de sort -- "$f1" > out), se "$f1"não puder ser aberto, outnão será criado / truncado e sortnem executado.

Para limpar alguma confusão possível (seguindo os comentários abaixo), isso não impede que o comando entre mmap()no arquivo ou lseek()dentro dele (não é o que sorttambém faz), desde que o próprio arquivo seja procurável. A única diferença é que o arquivo é aberto mais cedo e no descritor de arquivo 0 pelo shell, em vez de mais tarde pelo comando, possivelmente em um descritor de arquivo diferente. O comando ainda pode buscar / mmap que fd 0 como quiser. Isso não deve ser confundido com o local cat file | cmdonde cmdo stdin desta vez é um tubo que não pode ser mapeado / procurado.

Stéphane Chazelas
fonte
4
Lembre-se de que o uso de um redirecionamento obriga sorta ler os dados sequencialmente e você não pode mmapo arquivo. Embora sortpossa não ter muitos problemas, considere o desempenho de less <filee less file. No primeiro caso, lessé necessário manter todo o conteúdo do arquivo na memória; no segundo, é permitido ler apenas as partes que ele deseja. Agora imagine que fileseja um arquivo de log de 100 GB ...
isyrofo fly
7
@ styrofoamfly: É correto que less <filemantenha todo o arquivo na memória, mas não é obrigado a isso, é uma falha de menos. Somente cat file | lessé forçado a. Confira less /dev/fd/0 <f, que não mantém o arquivo na memória, mesmo que o receba no stdin. É um equívoco comum que stdin no Unix é inseparável. De fato, ele pode ser procurado, dependendo do tipo de arquivo.
pts
@styrofoamfly Você quer dizer que read()lê dados em seqüência de um arquivo, enquanto mmap()lê todo o arquivo na memória de uma só vez?
Tim
11
@JohnBollinger Não. Isso remonta a pelo menos desde o getys do SysIII em 1980 antes do início do projeto GNU e é necessário ter suporte para a maioria dos utilitários padrão, incluindo o sortPOSIX. Mas é verdade que nem sempre é suportado.
Stéphane Chazelas
2
Minhas desculpas, @ StéphaneChazelas, você está certo sobre a origem da convenção e, além disso, estipularei que a especificação POSIX para a getopt()função C reconhece esse significado do argumento --. Mas o ponto principal é o que você aceita: a manipulação de argumentos é o domínio de programas individuais, e nem todos tratam --especialmente.
John Bollinger
17

O problema é os nomes de arquivos que começam com um traço. sort "$f1"não funcionará se o valor de f1começar com, -porque o comando interpretará o valor como uma opção. Isso geralmente resulta em um erro, mas pode até causar uma falha de segurança . Com sort -- "$f1", o argumento double dash --significa "sem opções além deste ponto", portanto o valor de f1não será interpretado como uma opção. Mas ainda existe um caso extremo: se o valor de f1for um traço e nada mais, não será uma opção, é o argumento -, que significa “entrada padrão” (porque o argumento é um arquivo de entrada; para um arquivo de saída significaria "saída padrão").

Usar o redirecionamento evita todas essas armadilhas.

Isso se aplica à maioria dos comandos, não apenas sort.

Gilles 'SO- parar de ser mau'
fonte
Você está dizendo que sort < "$f1"isso funcionaria se o valor fosse igual a -? Não existe em nenhum shell que eu tentei.
grawity
@ grrawity, compare seq 10 > -; sort -com seq 10 > -; sort < -.
Stéphane Chazelas