¿Por qué ls
requiere un proceso separado para su ejecución? Sé la razón por la cual los comandos como cd
no se pueden ejecutar mediante un mecanismo de bifurcación, pero ¿hay algún daño si ls
se ejecuta sin bifurcación?
¿Por qué ls
requiere un proceso separado para su ejecución? Sé la razón por la cual los comandos como cd
no se pueden ejecutar mediante un mecanismo de bifurcación, pero ¿hay algún daño si ls
se ejecuta sin bifurcación?
Respuestas:
La respuesta es más o menos que ls
es un ejecutable externo. Puede ver su ubicación ejecutando type -p ls
.
¿Por qué no está ls
integrado en la carcasa, entonces? Bueno, ¿por qué debería ser? El trabajo de un shell no es abarcar todos los comandos disponibles, sino proporcionar un entorno capaz de ejecutarlos. Algunos proyectiles modernos tienen echo
, printf
y su tipo de construcción, que técnicamente no tienen que ser construidos, pero están hechos por razones de rendimiento cuando se ejecutan repetidamente (principalmente en bucles estrechos). Sin hacerlos incorporados, el shell tendría que bifurcarse y ejecutar un nuevo proceso para cada llamada, que podría ser extremadamente lento.
Por lo menos, ejecutar ls
, un ejecutable externo, requiere ejecutar una de la familia de llamadas de sistema ejecutivas. Usted podría hacer esto sin que se bifurcan, pero sería reemplazar la corteza primaria que está utilizando. Puede ver lo que sucede en esa instancia haciendo lo siguiente:
exec ls; echo "this never gets printed"
Dado que la imagen de proceso de su shell se reemplaza, el shell actual ya no es accesible después de hacer esto. Para que el shell pueda continuar ejecutándose después de ejecutar ls, el comando tendría que estar integrado en el shell.
La bifurcación permite reemplazar un proceso que no es su shell principal, lo que significa que puede continuar ejecutando su shell después.
echo
, printf
, etc.
cd
no es un ejecutable externo?
cd
ejecutable en los sistemas operativos compatibles con POSIX ( ver aquí ). Sin embargo, si desea realmente chdir () en el proceso actual, debe tenerlo integrado en el shell.
El Manual de referencia de Bash dice:
Los comandos incorporados son necesarios para implementar funcionalidades imposibles o inconvenientes de obtener con utilidades separadas.
Es decir, los shells están diseñados para incluir solo comandos integrados si:
El ls
comando no se ajusta a ninguno de los requisitos anteriores.
Sin embargo , aquí no hay ninguna restricción de programación que impida que ls
se implique como una función integrada, que se ejecuta en el mismo proceso que el intérprete de bash. Las razones de diseño para que los comandos no se impliquen como elementos integrados de shell son:
En cuanto a la primera razón: desea que el caparazón sea lo más independiente y flexible posible. No desea que el shell se atasque en ls
un montaje NFS que "no responde y sigue intentando".
En cuanto a la segunda razón: en muchos casos, es posible que desee utilizar un shell para un sistema que utiliza Busybox u otro sistema de archivos que tenga una ls
implementación diferente . O incluso use la misma fuente de shell en sistemas operativos que tienen ls
implementaciones diferentes .
En cuanto a la tercera razón: para expresiones como find . -type d | xargs ls -lad
sería difícil o imposible implementarlas ls
en el mismo proceso que el intérprete de shell.
En cuanto a la cuarta razón: algunos ls
comandos pueden tardar mucho tiempo en completarse. Es posible que desee que el shell continúe haciendo otra cosa mientras tanto.
Nota: Vea esta publicación útil de Warren Young en respuesta a una pregunta similar.
ls
en un proceso externo. Podría hacerse, pero sería complicado.
bash
salida alias | grep ls
. entradacat /etc/passwd | while read a; do echo "$a"; done
ls
No requiere un proceso separado. Muy pocos comandos requieren un proceso separado: solo los que necesitan cambiar los privilegios.
Como regla general, los shells implementan comandos como incorporados solo cuando esos comandos deben implementarse como incorporados. Los comandos como alias
, cd
, exit
, export
, jobs
, ... necesidad de leer o modificar algún estado interno de la cáscara, y por lo tanto no puede ser programas independientes. Los comandos que no tienen tales requisitos pueden ser comandos separados; De esta manera, se pueden llamar desde cualquier shell u otro programa.
Mirando la lista de incorporados en bash, solo los siguientes incorporados podrían implementarse como comandos separados. Para algunos de ellos, habría una ligera pérdida de funcionalidad.
command
- pero perdería su utilidad en situaciones en las que es PATH
posible que no se configure correctamente y el script se esté utilizando command
como parte de la configuración.echo
- Es una construcción para la eficiencia.help
- podría usar una base de datos separada, pero incrustar el texto de ayuda en el ejecutable del shell tiene la ventaja de hacer que el ejecutable del shell sea autónomo.kill
- Hay dos ventajas en tener un builtin incorporado: puede reconocer designaciones de trabajo además de las ID de proceso, y puede usarse incluso cuando no hay suficientes recursos para iniciar un proceso separado.printf
- por la misma razón que echo
, y también para admitir la -v
opción de poner la salida en una variable.pwd
- el incorporado ofrece la capacidad adicional de seguimiento lógico del directorio actual (dejando intactos los enlaces simbólicos en lugar de expandirlos).test
- Es una función integrada para la eficiencia (y bash también hace algo de magia con archivos llamados /dev/fd/…
en algunos sistemas operativos).Algunas conchas ofrecen un número significativo de incorporaciones adicionales. Hay faja , que es un shell diseñado para ser un binario independiente para reparaciones de emergencia (cuando algunos comandos externos pueden no ser utilizables). Tiene incorporado ls
, llamado -ls
, así como otras herramientas como -grep
y -tar
. Los componentes integrados de Sash tienen menos capacidades que los comandos completos. Zsh ofrece algunos componentes similares en su módulo zsh / files . No tiene ls
, pero la expansión comodín ( echo *
) y zstat
puede cumplir una función similar.
Creo que algo que falta a la gente aquí es la complejidad de corte del ls
programa GNU en Linux. Comparando el tamaño del ejecutable de ls
labash
y dash
conchas en mi sistema Debian, vemos que es bastante grande:
graeme@graeme:~$ ls -lh /bin/{ls,bash,dash}
-rwxr-xr-x 1 root root 953K Mar 30 2013 /bin/bash
-rwxr-xr-x 1 root root 115K Dec 25 20:25 /bin/dash
-rwxr-xr-x 1 root root 108K Jul 20 22:52 /bin/ls
Incluyendo un ls
versión tan completa como la versión GNU bash
aumentaría el tamaño del ejecutable en un 10%. ¡Es casi del mismo tamaño que la dash
carcasa completa !
La mayoría de los componentes integrados de shell se eligen porque se integran con el shell de una manera que los ejecutables externos no pueden (la pregunta señala cd
, pero otro ejemplo es la versión bash de kill
integrarse con el control de trabajo bash) o porque son comandos muy simples de implementar, dando una gran recompensa de velocidad vs tamaño ( true
y false
son casi tan simples como se pone).
GNU ls
ha tenido un largo ciclo de desarrollo e implementa muchas opciones para personalizar qué / cómo se muestran los resultados. El uso de un ls incorporado por defecto perdería esta funcionalidad o aumentaría significativamente la complejidad y el tamaño del shell.
Esto hace lo que buscas:
printf "%s\n" *
También puede almacenar nombres de archivo en una matriz:
files=(`printf "%s\n" *`) #items are separated by whitespace
echo ${#files[*]} files
for index in ${!a[*]}
do printf "%d: %s\n" $index ${a[$index]};
done
Pero no le importan los espacios en los nombres.
Esto pasa a variable y se preocupa por los espacios:
printf "%s\n" * | while read a; do echo $a; done
ls
es un programa externo,echo *
oecho * .*
(dependiendo de las opciones de shell) hace un trabajo bastante bueno de listar archivos sin bifurcación.