Uso de traço (-) no lugar de um nome de arquivo

110

Para um comando, se usar -como argumento no lugar de um nome de arquivo, significa STDIN ou STDOUT.

  1. Mas neste exemplo, ele cria um arquivo com o nome -:

    echo hello > -

    Como posso fazer -neste exemplo significar STDOUT?

  2. Por outro lado, como posso -significar um arquivo nomeado -em exemplos como:

    cat -
Tim
fonte
3
Como eu aparentemente tenho que ter 50 reputação para comentar diretamente ... No comentário / dev / stdin / dev / stdout, o AIX, que é um derivado legítimo do UNIX, não possui esses pseudodispositivos. E, como um comentário adicional, o LINUX não é um derivado do UNIX em nenhum caso. É um workalike compatível com POSIX e o mais popular dos sistemas operacionais UNIX-ish neste momento, mas não se engane, isso não é UNIX. Mas, a essência das respostas aqui está correta. A notação "-" não é interpretada como especial pelo shell e, portanto, é passada diretamente para cada aplicativo individual como um ARG. Se o aplicativo não reconhecer
Também há 2>&-construção, que significa "descritor próximo 2".
User3132194
@ user95873, o que suponho que você queira dizer é: enquanto o Linux é semelhante ao Unix, nem todo tipo Unix (ou UNIX verdadeiro) é Linux . A questão de saber se o Linux é ou não verdadeiro UNIX (ou seja, cumpre a Especificação Única do UNIX) não tem relação com o problema / dev / std {dentro, fora, erro}. Como / dev / std {in, out, err} é adicionado o recurso, não está faltando .
Sasha

Respostas:

156

Usar -como nome de arquivo para significar stdin / stdout é uma convenção usada por muitos programas. Não é uma propriedade especial do nome do arquivo. O kernel não reconhece -como especial, portanto, qualquer chamada do sistema que se refere a -um nome de arquivo será usada -literalmente como o nome do arquivo.

Com o redirecionamento do bash, -não é reconhecido como um nome de arquivo especial; portanto, o bash o usará como o nome do arquivo literal.

Quando catvê a string -como um nome de arquivo, trata-a como sinônimo de stdin. Para contornar isso, você precisa alterar a string que catvê de tal maneira que ainda se refere a um arquivo chamado -. A maneira usual de fazer isso é prefixar o nome do arquivo com um caminho - ./-, ou /home/Tim/-. Essa técnica também é usada para solucionar problemas semelhantes nos quais as opções de linha de comando se chocam com os nomes de arquivo; portanto, um arquivo chamado ./-enão aparece como a -eopção de linha de comando de um programa, por exemplo.

camh
fonte
37
Vale a pena acrescentar isso /dev/stdine /dev/stdoutestão universalmente disponíveis e podem ser usados ​​no lugar da -convenção.
jmtd
Também no catcaso, usar o redirecionamento em vez de listar o argumento pode ajudar cat <-:; no entanto, seria difícil combinar e concatenar isso com a concatenação de mais de um arquivo por vez.
jmtd
10
@jmtd: / dev / std {in, out} não estão disponíveis universalmente. Nem todos os unixes possuem.
Camh
2
Interessante, presumi que eles faziam parte do POSIX (mas não posso confirmar). Eles estão presentes pelo menos no Linux, BSDs e Solaris. Você pode dar um exemplo de um UNIX moderno que não possui?
Jmtd
1
@camh Não tenho certeza se você recebeu a notificação, e este é um tópico muito, muito antigo; Não tenho certeza se você pode, mas estou muito curioso se você souber a resposta para jmtda pergunta. :)
Swivel
18
  1. Em vez de echo hello > -, você pode usar echo hello > /dev/stdout.

    Enquanto '-' é uma convenção que tem de ser implementado por cada programa querer apoiá-lo, /dev/stdin, /dev/stdoute /dev/stderrsão, quando suportado pelo OS (pelo menos Solaris, Linux e BSDs fazer), independente da aplicação e, em seguida, vai funcionar como você pretender.

jlliagre
fonte
9

Como Camh mencionou , -é apenas uma convenção de nomenclatura usada por alguns programas. Se você quiser se referir a esses fluxos com um descritor de arquivo que o shell reconhecerá, o jiliagre estava correto ao usar o nome /dev/stdinou /dev/stdoutnão. Esses nomes de arquivo devem funcionar em qualquer lugar em que um nome de arquivo normal funcione.

  1. Dito isto, seu primeiro exemplo é meio bobo. Qualquer saída que seria capturada pelo operador de redirecionamento para gravar em um arquivo já está ativada na saída padrão; portanto, é inútil redirecioná-lo e gravá-lo de onde veio. O comportamento que você usa nesse canal é o pipe, não um redirecionamento:

    echo hello |
  2. No seu segundo exemplo, você simplesmente precisa dar alguma indicação de que deseja um arquivo literário com esse nome, não o apelido interno que ele possui. Você pode fazer isso mais facilmente, especificando um caminho para o arquivo como este:

    cat ./-
Caleb
fonte
6

Quanto ao 1, o programa precisa apoiá-lo. Você não pode simplesmente usá-lo arbitrariamente. Quanto a 2, redirecione a entrada de (por exemplo, cat < -).

bahamat
fonte
1

A abordagem '-' tem muitos problemas. Antes de tudo, requer uma interpretação do caractere '-' e muitos programas não realizam essa interpretação. Além disso, existem alguns programas que interpretam um hífen como um delimitador, marcando o final das opções da linha de comando. Os programas foram escritos para trabalhar com argumentos de nome de arquivo, a abordagem '-' é um hack, agradável, mas fraca.

A melhor maneira é:

$ echo hello > /dev/fd/1

/dev/stdout é um link simbólico de /dev/fd/1

b3h3m0th
fonte
O redirecionamento é interpretado pelo shell, não pelo programa que está sendo chamado.
precisa saber é o seguinte