En ocasiones, la sustitución del proceso no funcionará como se esperaba. Aquí hay un ejemplo:
Entrada:
gcc <(echo 'int main(){return 0;}')
Salida:
/dev/fd/63: file not recognized: Illegal seek
collect2: error: ld returned 1 exit status
Entrada:
Pero funciona como se esperaba cuando se usa con un comando diferente:
grep main <(echo 'int main(){return 0;}')
Salida:
int main(){return 0;}
He notado fallas similares con otros comandos (es decir, el comando que espera que el archivo de la sustitución del proceso no pueda usar /dev/fd/63
o similar). Este fracaso con gcc
es solo el más reciente. ¿Hay alguna regla general que deba tener en cuenta para determinar cuándo la sustitución del proceso fallará de esta manera y no debería usarse?
Estoy usando esta versión de BASH en Ubuntu 12.04 (también lo he visto en arch y debian):
GNU bash, versión 4.3.11 (1) -release (i686-pc-linux-gnu)
illegal seek
parece la respuesta: lo|pipe
quebash
apunta al programa ejecutado no es un archivo buscable. Probablemente si no puede tener éxitoecho data | command /dev/fd/0
en un programa, entonces tendrá una suerte similar w /<(cmd)
. No proporciona un archivo en el disco, solo sustituye un argumento que apunta a un descriptor de archivo de tubería.gcc -xc <(echo 'int main(){return 0;}')
(que establece el idiomaC
explícitamente).Respuestas:
La sustitución del proceso da como resultado un archivo especial (como
/dev/fd/63
en su ejemplo) que se comporta como el final de lectura de una tubería con nombre. Este archivo puede abrirse y leerse, pero no puede escribirse ni buscarse.Los comandos que tratan sus argumentos como flujos puros funcionan mientras que los comandos que esperan buscar en los archivos que reciben (o que les escriben) no funcionarán. El tipo de comando que el trabajo es lo que se considera generalmente como un filtro:
cat
,grep
,sed
,gzip
,awk
, etc ... Un ejemplo de un comando que no va a funcionar es un editor comovi
o una operación de archivo comomv
.gcc
desea poder realizar un acceso aleatorio en sus archivos de entrada para detectar en qué idioma están escritos. Si, en cambio, dagcc
una pista sobre el idioma del archivo de entrada, se complace en transmitir el archivo:La forma más simple y directa sin sustitución del proceso también funciona:
Tenga en cuenta que esto no es específico de
bash
. Todos los shells que admiten la sustitución de procesos se comportan de la misma manera.fuente
<()
formato debe actuar como un archivo para todos los efectos. De hecho, no conozco ningún comando que espere un archivo con el que no esté satisfecho<()
. Los que no funcionan son aquellos que esperan nombres de archivos , no archivos. Por ejemplo,grep -f
espera un archivo y funciona bien con<()
.<()
produce un nombre de archivo (la construcción se expande/proc/self/fd/something
en mi sistema). Este nombre, cuando se abre, actúa como el final de lectura de una canalización con nombre (S_IFIFO
) en lugar de un archivo normal (S_IFREG
) en el que se admitenread()
y otros, pero noseek()
.zsh
admite una tercera forma de sustitución de procesos que utiliza archivos temporales especialmente para ese fin:gcc =(echo 'int main(){return 0;}')
<(echo '...')
pero no con<(git show ...)
. alguna idea de por qué podría ser?ld
(que detecta formatos de objeto).-x
no es una pista; Es una declaración. Si lo especifica-x f95
, GCC pasará el archivo al compilador Fortran-95 independientemente de su nombre o contenido. Ver gcc.gnu.org/onlinedocs/gcc-8.1.0/gcc/Overall-Options.html