Utilisation de tiret (-) à la place d'un nom de fichier

110

Pour une commande, utiliser -comme argument à la place d'un nom de fichier signifiera STDIN ou STDOUT.

  1. Mais dans cet exemple, il crée un fichier avec le nom suivant -:

    echo hello > -

    Comment puis-je faire -dans cet exemple signifie STDOUT?

  2. Inversement, comment faire en sorte -qu'un fichier soit nommé -dans des exemples tels que:

    cat -
Tim
la source
3
Comme je dois apparemment avoir 50 réputation pour commenter directement ... Sur le commentaire / dev / stdin / dev / stdout, AIX, qui est un dérivé légitime de UNIX, ne possède pas ces pseudodonnées. De plus, LINUX n’est en aucun cas un dérivé d’UNIX. C'est un workalike compatible POSIX, et le plus populaire des systèmes d'exploitation UNIX-ish à ce stade, mais ne vous y trompez pas, ce n'est pas UNIX. Mais l'essentiel des réponses est correct. La notation "-" n’est pas interprétée comme spéciale par le shell et est donc transmise directement à chaque application en tant qu’ARG. Si l'application ne
Il y a aussi la 2>&-construction, ce qui signifie "descripteur proche 2".
user3132194
@ user95873, ce que je suppose que vous vouliez dire, c'est que si Linux est semblable à Unix, tous les appareils semblables à Unix (ou véritablement UNIX) ne sont pas Linux . La question de savoir si Linux est ou non vrai UNIX (c'est-à-dire conforme à la spécification Single UNIX) n'a pas de rapport avec / dev / std {in, out, err}. Comme / dev / std {in, out, err} est une fonctionnalité ajoutée , elle ne manque pas .
Sasha

Réponses:

156

Utiliser -comme nom de fichier pour signifier stdin / stdout est une convention utilisée par de nombreux programmes. Ce n'est pas une propriété spéciale du nom de fichier. Le noyau ne reconnaît pas -comme spécial, donc tous les appels système référant à -un nom de fichier utiliseront -littéralement le nom de fichier.

Avec la redirection bash, -n’est pas reconnu comme un nom de fichier spécial, bash l’utilisera donc comme nom de fichier littéral.

Lorsqu'il catvoit la chaîne -comme un nom de fichier, il la traite comme un synonyme de stdin. Pour contourner ce problème, vous devez modifier la chaîne qui est vue catde manière à ce qu'elle se réfère toujours à un fichier appelé -. La méthode habituelle consiste à préfixer le nom du fichier avec un chemin - ./-, ou /home/Tim/-. Cette technique est également utilisée pour résoudre des problèmes similaires dans lesquels les options de ligne de commande entrent en conflit avec les noms de fichiers. Ainsi, un fichier nommé ./-en'apparaît pas comme l' -eoption de ligne de commande d'un programme, par exemple.

camh
la source
37
Cela vaut la peine d’ajouter cela, /dev/stdinil /dev/stdoutest universellement disponible et peut être utilisé à la place de la -convention.
Jmtd
Également dans le catcas, utiliser la redirection au lieu de lister l'argument pourrait aider cat <-:; Cependant, il serait difficile de combiner cela avec la concaténation de plusieurs fichiers à la fois.
Jmtd
10
@jmtd: / dev / std {in, out} ne sont pas universellement disponibles. Tous les Unix n'en ont pas.
camh
2
Intéressant, j'ai supposé qu'ils faisaient partie de POSIX (mais ne peux pas confirmer). Ils sont présents au moins sur Linux, les BSD et Solaris. Pouvez-vous donner un exemple d'UNIX moderne qui en manque?
Jmtd
1
@camh Pas sûr que vous ayez reçu la notification, et c'est un sujet très, très vieux; Je ne sais pas si vous le pouvez, mais je suis très curieux de savoir si vous connaissez la réponse à jmtdla question. :)
Pivot
18
  1. Au lieu de echo hello > -, vous pouvez utiliser echo hello > /dev/stdout.

    Alors que '-' est une convention qui doit être mise en œuvre par chaque programme souhaitant la prendre en charge /dev/stdin, /dev/stdoutet /dev/stderrqui, une fois pris en charge par le système d’exploitation (au moins Solaris, Linux et les BSD), sont indépendants de l’application, puis fonctionnent comme vous le souhaitez. l'intention.

jlliagre
la source
9

Comme camh l'a mentionné , ce -n'est qu'une convention de nommage utilisée par certains programmes. Si vous voulez faire référence à ces flux avec un descripteur de fichier reconnu par le shell, jiliagre a eu raison de vous demander d' utiliser le nom /dev/stdinou /dev/stdoutplutôt. Ces noms de fichiers doivent fonctionner n'importe quel endroit où un nom de fichier normal fonctionnerait.

  1. Cela étant dit, votre premier exemple est un peu ridicule. Toute sortie qui serait interceptée par l'opérateur de redirection pour écrire dans un fichier est déjà en sortie standard, donc le rediriger et l'écrire à sa source est inutile. Le comportement que vous utilisez là-bas est le tuyau, pas une redirection:

    echo hello |
  2. Dans votre deuxième exemple, vous devez simplement indiquer une indication que vous souhaitez un fichier littéral portant ce nom, et non son alias interne. Vous pouvez faire cela plus facilement en spécifiant un chemin d'accès au fichier comme ceci:

    cat ./-
Caleb
la source
6

Pour 1, le programme doit le soutenir. Vous ne pouvez pas l'utiliser de manière arbitraire. Quant à 2, redirige l'entrée de (par exemple cat < -).

bahamat
la source
1

L'approche '-' a beaucoup de problèmes. Tout d'abord, cela nécessite une interprétation du caractère '-' et de nombreux programmes n'effectuent pas une telle interprétation. De plus, certains programmes interprètent un trait d'union comme un séparateur marquant la fin des options en ligne de commande. Les programmes sont écrits pour fonctionner avec des arguments de nom de fichier, l'approche '-' est un hack, sympa mais faible.

Le meilleur moyen est:

$ echo hello > /dev/fd/1

/dev/stdout est un lien symbolik de /dev/fd/1

b3h3m0th
la source
La redirection est interprétée par le shell, pas par le programme appelé.
sherrellbc