Uso del guión (-) en lugar de un nombre de archivo

110

Para un comando, si se usa -como argumento en lugar de un nombre de archivo significará STDIN o STDOUT.

  1. Pero en este ejemplo, crea un archivo con el nombre -:

    echo hello > -

    ¿Cómo puedo hacer que -en este ejemplo signifique STDOUT?

  2. Por el contrario, ¿cómo puedo hacer que -signifique un archivo nombrado -en ejemplos como:

    cat -
Tim
fuente
3
Como aparentemente tengo que tener 50 reputación para comentar directamente ... En el comentario / dev / stdin / dev / stdout, AIX, que es un derivado legítimo de UNIX, no tiene estos pseudodispositivos. Y, como comentario adicional, LINUX no es un derivado de UNIX en ningún caso. Es un workalike compatible con POSIX, y el más popular de los sistemas operativos UNIX en este momento, pero no se equivoquen, esto no es UNIX. Pero, la esencia de las respuestas aquí es correcta. La notación "-" no se interpreta como especial por el shell y, por lo tanto, se pasa directamente a cada aplicación individual como un ARG. Si la aplicación no
También hay 2>&-construcción, que significa "descriptor cercano 2".
user3132194
@ user95873, lo que supongo que quería decir es: mientras que Linux es similar a Unix, no todos los similares a Unix (o UNIX verdadero) son Linux . La cuestión de si Linux es o no cierto UNIX (es decir, cumple con la especificación UNIX simple) no tiene relación con el problema / dev / std {in, out, err}. Como / dev / std {in, out, err} se agrega la característica, no falta .
sasha

Respuestas:

156

Usar -como nombre de archivo para significar stdin / stdout es una convención que utilizan muchos programas. No es una propiedad especial del nombre del archivo. El núcleo no se reconoce -como especial, por lo que cualquier llamada al sistema que se refiera -como nombre de archivo se usará -literalmente como nombre de archivo.

Con la redirección de bash, -no se reconoce como un nombre de archivo especial, por lo que bash lo usará como el nombre de archivo literal.

Cuando catve la cadena -como un nombre de archivo, la trata como un sinónimo de stdin. Para evitar esto, debe modificar la cadena que se catve de tal manera que todavía se refiere a un archivo llamado -. La forma habitual de hacer esto es prefijar el nombre del archivo con una ruta - ./-, o /home/Tim/-. Esta técnica también se usa para solucionar problemas similares en los que las opciones de la línea de comandos chocan con los nombres de archivo, por lo que un archivo al que se ./-ehace referencia no aparece como la -eopción de línea de comando para un programa, por ejemplo.

camh
fuente
37
Vale la pena agregar eso /dev/stdiny /dev/stdoutestán disponibles universalmente y se pueden usar en lugar de la -convención.
jmtd
También en el catcaso, mediante la redirección en lugar de enumerar el argumento podría ayudar: cat <-; sin embargo, sería difícil mezclar y combinar eso con la concatenación de más de un archivo a la vez.
jmtd
10
@jmtd: / dev / std {in, out} no están disponibles universalmente. No todos los unixes lo tienen.
camh
2
Interesante, supuse que eran parte de POSIX (pero no puedo confirmar). Están presentes al menos en Linux, los BSD y Solaris. ¿Puedes dar un ejemplo de un UNIX moderno que carece de ellos?
jmtd
1
@camh No estoy seguro si recibió la notificación, y este es un tema muy, muy antiguo; No estoy seguro si puedes, pero tengo mucha curiosidad si sabes la respuesta a jmtdla pregunta. :)
Girar el
18
  1. En lugar de echo hello > -, puedes usar echo hello > /dev/stdout.

    Mientras '-' es una convención que tiene que ser implementado por cada programa que quieran apoyarlo, /dev/stdin, /dev/stdouty /dev/stderrson, cuando son apoyados por el sistema operativo (al menos Solaris, Linux y BSD lo hacen), independientemente de la aplicación y luego funcionará como usted intentar.

jlliagre
fuente
9

Como mencionó Camh , -es solo una convención de nomenclatura utilizada por algunos programas. Si desea hacer referencia a estas transmisiones con un descriptor de archivo que el shell reconocerá, jiliagre estuvo en lo correcto al usar el nombre /dev/stdino, en su /dev/stdoutlugar. Esos nombres de archivo deberían funcionar en cualquier lugar donde funcionaría un nombre de archivo normal.

  1. Dicho esto, tu primer ejemplo es un poco tonto. Cualquier salida que sea capturada por el operador de redireccionamiento para escribir en un archivo ya está en la salida estándar, por lo que redirigirla y volver a escribirla de donde vino no sirve de nada. El comportamiento que usa allí es la tubería, no una redirección:

    echo hello |
  2. En su segundo ejemplo, simplemente necesita dar alguna indicación de que desea un archivo literal con ese nombre, no el alias interno que tiene. Puede hacerlo más fácilmente especificando una ruta al archivo como esta:

    cat ./-
Caleb
fuente
6

En cuanto a 1, el programa tiene que apoyarlo. No puedes usarlo arbitrariamente. En cuanto a 2, redirija la entrada desde (por ejemplo, cat < -).

bahamat
fuente
1

El enfoque '-' tiene muchos problemas. En primer lugar, requiere una interpretación del carácter '-' y muchos programas no realizan dicha interpretación. Y además, hay algunos programas que interpretan un guión como un delimitador que marca el final de las opciones de línea de comando. Los programas están escritos para trabajar con argumentos de nombre de archivo, el enfoque '-' es un truco, agradable pero débil.

La mejor manera es:

$ echo hello > /dev/fd/1

/dev/stdout es un enlace simbólico de /dev/fd/1

b3h3m0th
fuente
La redirección es interpretada por el shell, no por el programa que se invoca.
sherrellbc