Tengo una función Bash para mostrar las páginas de manual representadas como postscript, en un PDF:
function psman () {
man -t "$@" | ps2pdf - /tmp/manpage.pdf
evince /tmp/manpage.pdf
}
( Actualizar : Eliminé las complicaciones periféricas como generar dinámicamente el nombre del archivo temporal y usar 'nohup')
Esto funciona bien. Para una captura de pantalla en uso, vea https://www.tartley.com/postscript-formatted-man-pages .
Para mi propia edificación, traté de implementarla sin usar archivos temporales. Por ejemplo, utilizando la sustitución de procesos:
$ evince <(man -t ls | ps2pdf - -)
Esto no funciona. Evince muestra un error en su GUI:
Unable to open document "file:///dev/fd/63".
PDF document is damaged
¿Por qué? ¿Cómo puedo generar y ver el PDF sin generar ningún archivo intermedio?
El mensaje de error anterior es diferente de lo que muestran los mensajes de los archivos faltantes o vacíos, así que no es simplemente eso.
Actualizar: Para obtener más información, intenté reemplazar 'evince' con 'ls':
$ ls -l <(man -t ls | ps2pdf - -)
lr-x------. 1 jhartley jhartley 64 Aug 23 08:59 /dev/fd/63 -> pipe:[196475]
donde dircolors es colorante:
/dev/fd/63
como 'ORPHAN' (un enlace simbólico que apunta a un archivo inexistente), ypipe:[196475]
como 'MISSING' (un archivo inexistente apuntado por un enlace simbólico)
Entonces, ¿quizás a Evince se le está dando un enlace que apunta a un archivo que no existe? Para imitar esto, creé un enlace simbólico que apunta a un archivo inexistente, luego lo abrí con 'evince'. Pero en lugar del mensaje "El PDF está dañado" más arriba, esto me da "No existe tal archivo o directorio".
Actualizar: Creo que los tipos de archivo ORPHAN / MISSING son una pista falsa. Veo el mismo enlace simbólico ORPHAN / MISSING cuando hago una sustitución de proceso muy simple:
$ ls -l <( echo 123 )
y usando el mismo man|ps2pdt
La tubería funciona bien cuando la sustitución del proceso se alimenta a diff
:
$ diff <(man -t ls | ps2pdf - - | tr "\0" "0") <(man -t ls | ps2pdf - - | tr "\0" "0")
248c248
< /ID [<95A81B38FAE8E6FE3C899586A1DEE861><95A81B38FAE8E6FE3C899586A1DEE861>]
---
> /ID [<2F9164BD9265C8540A4A8E7068076344><2F9164BD9265C8540A4A8E7068076344>]
(Aquí agregué 'tr' a las tuberías para eliminar los caracteres nulos / cero en la salida pdf, de modo que diff trataría los archivos como textuales en lugar de binarios).
Entonces, en resumen, no tengo idea de por qué recibo el error "El PDF está dañado" más arriba. Mi objetivo, aparte de comprender, es ver el PDF generado sin generar ningún archivo en el camino.
evince <( cat man-ls.pdf )
se abre sin errores, mostrando 4 páginas (el número correcto), pero todas las páginas están en blanco. Como si en parte hubiera leído el archivo con éxito, pero luego falló en algún punto.Respuestas:
Solo una conjetura, pero plausible:
evince
busca a través del "archivo", la secuencia que recibe no se puede buscar. Comparar ¿Por qué la sustitución del proceso BASH no funciona con algunos comandos?Esto significa que es (¿casi?) Imposible lograr lo que desea sin ningún archivo intermedio. Lo mejor que se me ocurre es un guión como este:
Observaciones, trampas, etc .:
$tmpd
es/dev/shm
, se crea un archivo temporal en memoria . Supongo que es lo más cercano a "sin generar ningún archivo intermedio" que pueda obtener fácilmente, al tiempo que lo puede buscar.mktemp
yrm
, el archivo sobrevive y no lo queremos. Hay pocos enfoques para este problema, puedetrap
Señales si quieres; Elegí ejecutar toda la secuencia en segundo plano (( … ) &
) que puede ser lo suficientemente bueno.evince
no abrirá un archivo de/dev/shm
a menos que su nombre termine con.pdf
(Este comportamiento es insensible a mayúsculas y minúsculas). Por eso hay.pdf
en la plantilla de nombre de archivo. No hay tal problema en/tmp
. ¿Por qué? No lo sé.$*
en ella para hacerla algo significativa (se muestra en el título deevince
ventana).fuente
Los archivos PDF son una colección de objetos interrelacionados, identificados con identificadores. Al final del archivo, hay un índice para los objetos, que asigna las identificaciones a las compensaciones de archivos. Es realmente imposible utilizar un archivo PDF sin este índice, por lo que el enfoque habitual para leer un archivo PDF es intentar cerrar el final e intentar encontrar el principio del índice, que luego se lee en la memoria. El índice indica qué objeto es el objeto raíz, y desde allí puede recorrer el gráfico del objeto, utilizando siempre el índice para encontrar el desplazamiento del archivo de cada objeto relacionado.
En teoría, podría leer (o mmap) todo el archivo en la memoria, pero eso no funcionaría con archivos realmente grandes y el PDF está destinado a poder hacer frente a archivos realmente grandes (y, de hecho, los archivos PDF con calidad de impresión pueden ser realmente grande). Por lo tanto, la búsqueda es una parte intrínseca del uso de un archivo PDF, y la sustitución de procesos no es compatible con la búsqueda.
Hay otras aplicaciones de línea de comando que necesitan buscar, o pensar que lo hacen. (A veces, la búsqueda es solo un intento del programador para averiguar qué tan grande es el archivo, por conveniencia). Hay otros formatos de archivo que ponen un índice al final (como la compresión Zip), y realmente se basan en la búsqueda. Las bases de datos, por ejemplo, ni siquiera tienen un sentido de lectura lineal, y probablemente nadie pensaría en proporcionar un archivo de respaldo de base de datos a través de la sustitución de procesos. Pero el PDF es un tipo de elemento secundario para el procesamiento no lineal, y eso a veces es sorprendente.
fuente
Solo necesita agregar el nombre del archivo, por ejemplo, use:
(man -t ls | ps2pdf - ~/man_ls.pdf) > evince
Esto va a crear el
man_ls.pdf
archivo en su directorio personalfuente
cmd1 <( cmd2 )
sintaxis. El stdout decmd2
(en mi ejemplo, ps2pdf) va a una tubería, y esa tubería recibe un nombre en el sistema de archivos, y ese nombre se pasa a cmd1 (en mi ejemplo, evince). cmd1 puede abrir el nombre de archivo que se le dio, leerlo y obtener la salida estándar de cmd2. Ninguno de los dos comandos tiene idea de que se está utilizando la sustitución de procesos. Sin embargo, en ningún momento Bash escribe bytes en el disco. Esto es todo en memoria, al igual que la redirección y amp; tubería. El punto es para el rendimiento, & amp; educacion personal