¿Dónde puedo encontrar el script de shell para el comando ls?

¿Dónde puedo encontrar el script de shell para el comando ls?

Estoy tratando de entender cómo lsfunciona el comando y supongo que hay un script de shell que define lsalgún lugar del sistema de archivos. ¿Esto correcto? Si es así, ¿dónde puedo encontrarlo?

Respuesta1

lsutiliza 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

lsno es un script de shell, si ejecuta fileel 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:

  1. coreutils-8.22-22.fc21.src.rpm es mío, su número de paquete puede variar.

  2. Algunos comandos como type -a historydevolver "el historial es un shell incorporado", debe mirar el código fuente del shell actual, es decir rpm -qf `readlink -f /proc/$$/exe`(Detectar el shell actual por comando escomplicadode lo que piensas, este truco no funciona en fishshell)

  3. En csh/tcsh shell, debe usar where historyporque no existe tal typecomando. Se pueden encontrar más detallesaquí.

  4. 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 desde repoqueryarriba 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.rpm

  5. Puede 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...

información relacionada