
Estoy tratando de entender cómo ls
funciona el comando y supongo que hay un script de shell que define ls
algún lugar del sistema de archivos. ¿Esto correcto? Si es así, ¿dónde puedo encontrarlo?
Respuesta1
ls
utiliza opendir()
y readdir()
recorrer todos los archivos del directorio. Si necesita más información sobre alguno de ellos llama stat()
. Lea la fuente, por supuesto, pero un atajo muy útil es:
# strace ls
La parte clave con un par de comentarios es:
Obtener las entradas del directorio
open(".", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC) = 3
fcntl64(3, F_GETFD) = 0x1 (flags FD_CLOEXEC)
getdents64(3, /* 53 entries */, 32768) = 1744
getdents64(3, /* 0 entries */, 32768) = 0
close(3) = 0
Verificar que la salida estándar sea un dispositivo de caracteres
fstat64(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 0), ...}) = 0
asignar stdin a la memoria. (No estoy seguro de por qué, consulte la fuente)
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1,
0) = 0xb73ff000
escriba las entradas del directorio en stdout y cierre
write(1, "bin Desktop Documents Downloa"..., 91bin Desktop
Documents Download Music Pictures Public public_html Templates
Videos
) = 91
close(1) = 0
munmap(0xb73ff000, 4096) = 0
close(2) = 0
exit_group(0) = ?
Respuesta2
ls
no es un script de shell, si ejecuta file
el comando, sabrá que es un archivo ejecutable ELF LSB de 64 bits:
$ type -a ls
ls is aliased to `ls --color=auto'
ls is /usr/bin/ls #<---- now we know the file path of `ls`
ls is /bin/ls
$
$ file /usr/bin/ls
/usr/bin/ls: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=ddf8cdb3f1fd2e8263637b7c8ccea84fbf41ee3c, stripped
$
Puedes encontrar el código fuente en línea.aquí.
O si su distribución es una distribución de Linux basada en RPM + dnf
, entonces puede:
$ rpm -qf /usr/bin/ls
coreutils-8.22-22.fc21.x86_64 #so now we know the package name is coreutils
$ sudo dnf whatprovides /usr/bin/ls #alternative way
Using metadata from Mon May 16 02:39:55 2016 (1 day, 23:03:50 hours old)
coreutils-8.22-22.fc21.x86_64 : A set of basic GNU tools commonly used in shell scripts
Repo : @System
coreutils-8.22-19.fc21.x86_64 : A set of basic GNU tools commonly used in shell scripts
Repo : fedora
coreutils-8.22-22.fc21.x86_64 : A set of basic GNU tools commonly used in shell scripts
Repo : updates
$
$ mkdir coreutils #optional
$ cd coreutils #optional
$ sudo dnf download --source coreutils
...
$ rpm2cpio coreutils-8.22-22.fc21.src.rpm |cpio -idmv
...
$ sudo rm coreutils-8.22-22.fc21.src.rpm #optional
$ unp coreutils-8.22.tar.xz
...
$ rm coreutils-8.22.tar.xz #optional
$ cd coreutils-8.22/
$ find . -iname 'ls*'
./lib/lseek.c
./lib/lstat.c
./src/ls.c #<---- now we know ls.c is here
./src/ls-vdir.c
./src/ls.h
./src/ls-ls.c
./src/ls-dir.c
./man/ls.x
./tests/ls
./tests/misc/ls-misc.pl
./tests/misc/ls-time.sh
./m4/ls-mntd-fs.m4
./m4/lstat.m4
./m4/lseek.m4
$ vi ./src/ls.c
Nota:
coreutils-8.22-22.fc21.src.rpm es mío, su número de paquete puede variar.
Algunos comandos como
type -a history
devolver "el historial es un shell incorporado", debe mirar el código fuente del shell actual, es decirrpm -qf `readlink -f /proc/$$/exe`
(Detectar el shell actual por comando escomplicadode lo que piensas, este truco no funciona enfish
shell)En csh/tcsh shell, debe usar
where history
porque no existe taltype
comando. Se pueden encontrar más detallesaquí.También puede interesarle probar el comodín, por ejemplo,
repoquery --resolve --archlist=src '*compress*'
para incluir paquetes no instalados (tenga cuidado si el comando de consulta es como '*uncompress*'; en este caso, debe eliminar el prefijo 'un' para limitar si el primer intento es '*uncompress*'). fallido). La salida desderepoquery
arriba necesita eliminar el medio.0:y opcionalmente postfix con.rpmpara obtener el nombre completo correcto que puede utilizar para buscar enhttp://rpm.pbone.net, por ejemplo, ncompress-0:4.2.4.4-3.fc21.src cámbielo a ncompress-4.2.4.4-3.fc21.src.rpmPuede habilitar la depuración de espejo cuando dnf descarga la fuente, en caso de que el servidor espejo no funcione. Vereste.
[ACTUALIZAR]
En caso de que tenga un error de rpm debido a repositorios no válidos como yo, así es como lo solucioné:
$ sudo dnf config-manager --set-enabled '*' #Enable all repos, at anytime, check with `sudo dnf repolist all`
$ repoquery --resolve --archlist=src '*compress*'
Could not match packages: failure: repodata/repomd.xml from rpmfusion-free-rawhide-source: [Errno 256] No more mirrors to try.
http://free.nchc.org.tw/rpmfusion/free/fedora/development/rawhide/source/SRPMS/repodata/repomd.xml: [Errno 14] HTTP Error 404 - Not Found
...
$ repoquery --resolve --archlist=src --enablerepo='*source' --disablerepo='rpmfusion-free-rawhide-source' '*compress*' #not works too
...
$ sudo yum-config-manager --save --disablerepo=rpmfusion-nonfree-rawhide-source #for unknown reason, it doesn't work
$ sudo dnf config-manager --set-disabled rpmfusion-free-rawhide-source #for unknown reason, it doesn't work
$ grep -rnIH -D skip --color=always rpmfusion-free-rawhide-source /etc/yum.repos.d/
/etc/yum.repos.d/rpmfusion-free-rawhide.repo:17:[rpmfusion-free-rawhide-source]
$ sudo vi /etc/yum.repos.d/rpmfusion-free-rawhide.repo #Edit rpmfusion-free-rawhide-source from enabled=1 to enabled=0
$ repoquery --resolve --archlist=src '*compress*'#now should works :) repeat the `grep and vi` steps above if got error in other repos, in my case i have to disable rpmfusion-nonfree-rawhide-source too.
PD:Edite el título de [rpmfusion-free-rawhide-source] a [rpmfusion-free-rawhide-sourceDESACTIVAR] hack debería hacer que --enablerepo='*source' funcione, aunque hasta ahora encontré que es innecesario porque ya habilité todos los repositorios en el primer comando.
Respuesta3
No sé si esa es una respuesta porque ls está escrito en C, pero puedes escribir un script de shell para hacer un "ls" usando el bucle for:
para f en *;hacer eco $f; hecho
También es útil en algunos shells estáticos...