Sé que usar el comando ls
enumerará todos los directorios. Pero, ¿qué hace el ls *
comando? Lo usé y solo enumera los directorios. ¿La estrella en frente de ls
significa qué tan profundo puede enumerar los directorios?
ls
enumera los archivos y el contenido de los directorios que se pasan como argumentos, y si no se proporciona ningún argumento, enumera el directorio actual. También se le puede pasar una serie de opciones que afectan su comportamiento (ver man ls
para más detalles).
Si ls
se le pasa un argumento llamado *
, buscará un archivo o directorio llamado *
en el directorio actual y lo enumerará como cualquier otro. ls
no trata al *
personaje de ninguna otra forma que no sea otra.
Sin embargo, si se ls *
trata de una línea de comando de shell , el shell lo expandirá de *
acuerdo con las reglas de globbing del shell correspondiente (también denominado Generación de nombre de archivo o Expansión de nombre de archivo ).
Si bien diferentes shells admiten diferentes operadores de globbing, la mayoría de ellos están de acuerdo con el más simple *
. *
como patrón significa cualquier número de caracteres, por lo *
que glob
se expandirá a la lista de archivos en los directorios actuales que coinciden con ese patrón. Sin embargo, existe la excepción de que un carácter de punto ( .
) en un nombre de archivo debe coincidir explícitamente, por lo que en *
realidad se expande a la lista de archivos y directorios que no comienzan con .
(en orden lexicográfico).
Por ejemplo, si el directorio actual contiene los archivos llamados .
, ..
, .foo
, -l
y foo bar
, *
se ampliará por la cáscara de dos argumentos para transmitir a ls
: -l
y foo bar
, por lo que será como si lo hubiera escrito:
ls -l "foo bar"
o
'ls' "-l" foo\ bar
Cuáles son tres formas de ejecutar exactamente el mismo comando. En los 3 casos, el ls
comando (que probablemente se ejecutará desde /bin/ls
una búsqueda de directorios mencionada en $PATH
) se pasará por esos 3 argumentos: "ls", "-l" y "foo bar".
Por cierto, en este caso, ls
tratará el primero (estrictamente hablando segundo ) como una opción.
Ahora, como dije, diferentes proyectiles tienen diferentes operadores de globos. Hace unas décadas, zsh
introduje el **/
operador¹, que significa hacer coincidir cualquier nivel de subdirectorios, abreviatura (*/)#
y ***/
que es lo mismo, excepto que sigue enlaces simbólicos mientras desciende los directorios.
Hace unos años (julio de 2003 ksh93o+
), ksh93
decidió copiar ese comportamiento, pero decidió hacerlo opcional y solo cubrió el **
caso (no ***
). Además, si bien **
solo no era especial en zsh
(solo significaba lo mismo que *
en otros shells tradicionales, ya que **
significa cualquier número de caracteres seguido de cualquier número de caracteres), en ksh93, **
significaba lo mismo que **/*
(por lo que cualquier archivo o directorio debajo del actual (excluyendo archivos ocultos).
bash
copiado ksh93
unos años más tarde (febrero de 2009, bash 4.0), con la misma sintaxis pero con una desafortunada diferencia: bash **
era como zsh
's ***
, es decir, seguía enlaces simbólicos cuando recurría a subdirectorios que generalmente no es lo que quieres que haga y puede tener efectos secundarios desagradables. Se corrigió parcialmente en bash-4.3 en que los enlaces simbólicos todavía se seguían, pero la recursión se detuvo allí. Fue completamente reparado en 5.0.
yash
agregado **
en la versión 2.0 en 2008, habilitado con la extended-glob
opción. Su implementación es más cercana a zsh
la de que **
solo no es especial. En la versión 2.15 (2009), agregó ***
like en zsh
y dos de sus propias extensiones: .**
e .***
incluir directorios ocultos al recurrir (en zsh
, el D
calificador glob (como en **/*(D)
) considerará archivos y directorios ocultos, pero si solo desea atravesar ocultos dirs pero no expandir archivos ocultos, necesita ((*|.*)/)#*
o **/[^.]*(D)
).
La concha de pescado también es compatible **
. Al igual que la versión anterior de bash
, sigue enlaces simbólicos al descender el árbol de directorios. En ese shell, sin embargo, **/*
no es lo mismo que **
. **
es más una extensión de *
que puede abarcar varios directorios. En fish
, **/*.c
coincidirá a/b/c.c
pero no a.c
, mientras que a**.c
coincidirá a.c
e ab/c/d.c
y zsh
's **/.*
, por ejemplo, tiene que ser por escrito .* **/.*
. Allí, ***
se entiende como **
seguido por *
lo mismo que **
.
tcsh
También agregó una globstar
opción en V6.17.01 (mayo de 2010) y admite ambos **
y ***
à la zsh
.
Así pues, en tcsh
, bash
y ksh93
, (cuando la opción correspondiente está activada ( globstar
)) o fish
, **
expande todos los archivos y directorios por debajo de la actual, y ***
es la misma que **
para fish
un enlace simbólico atravesar **
para tcsh
con globstar
, y al igual que *
en bash
y ksh93
(aunque es no es imposible que las futuras versiones de esos shells también atraviesen enlaces simbólicos).
Arriba, habrá notado la necesidad de asegurarse de que ninguna de las expansiones se interprete como una opción. Para eso, harías:
ls -- *
O:
ls ./*
Hay algunos comandos (no importa ls
) donde el segundo es preferible ya que incluso con --
algunos nombres de archivo pueden tratarse especialmente. Es el caso de -
la mayoría de utilidades de texto, cd
y pushd
y nombres de archivo que contienen el =
carácter de awk
por ejemplo. Preceder ./
a todos los argumentos elimina su significado especial (al menos para los casos mencionados anteriormente).
También debe tenerse en cuenta que la mayoría de los shells tienen una serie de opciones que afectan el comportamiento global (como si los archivos de puntos se ignoran o no, el orden de clasificación, qué hacer si no hay coincidencia ...), vea también el $FIGNORE
parámetro enksh
Además, en todos los depósitos, pero csh
, tcsh
, fish
y zsh
, si el patrón de comodines no coincide con ningún archivo, el patrón se pasa como argumento sin expandir lo que provoca confusión y posiblemente insectos. Por ejemplo, si no hay un archivo no oculto en el directorio actual
ls *
Realmente llamará ls
con los dos argumentos ls
y *
. Y como no hay ningún archivo, por lo que *
tampoco se llama ninguno, verá un mensaje de error de ls (no el shell) como:, ls: cannot access *: No such file or directory
que se sabe que hace que la gente piense que fue ls
eso lo que realmente estaba expandiendo los globos.
El problema es aún peor en casos como:
rm -- *.[ab]
Si no hay *.a
ni *.b
archivo en el directorio actual, entonces es posible llegar a borrar un archivo llamado *.[ab]
por error ( csh
, tcsh
y zsh
reportaría un ningún partido de error y no llamarían rm
(y fish
no soporta los [...]
comodines)).
Si desea pasar un literal *
a ls
, debe citar ese *
carácter de alguna manera como en ls \*
o ls '*'
o ls "*"
. En shells similares a POSIX, el globbing se puede desactivar por completo usando set -o noglob
o set -f
(este último no funciona a zsh
menos que en sh
/ ksh
emulación).
¹ Si bien (*/)#
siempre fue compatible, primero fue breve como ..../
en zsh-2.0 (y posiblemente antes), luego ****/
en 2.1 antes de obtener su forma definitiva **/
en 2.2 (principios de 1992)
find -name *
. Especialmente con patrones más complejos, si hay exactamente una coincidencia en el directorio actual, las personas a menudo no se darán cuenta de que no están pasando el asteriscofind
.*.[ab]
intentaría eliminar todo lo que termina en.[ab]
.[
No es especial en pescado.El comando
ls
predeterminado esls .
: Listar todas las entradas en el directorio actual .El comando
ls *
significa 'ejecutar ls en la expansión del*
patrón de shell'El
*
shell procesa el patrón y se expande a todas las entradas en el directorio actual, excepto aquellas que comienzan con a.
. Irá un nivel más profundo.La interpretación de
*
patrones dobles o triples depende del caparazón real utilizado.*
es un comodín que coincide con 0 o más caracteres. Algunos proyectiles modernos se repetirán en subdirectorios al ver el**
patrón.fuente
*
hacen añadir algo, ver la otra respuesta que explica la Globstar. También debe quedar claro que ls no tiene nada que ver con los asteriscos, nunca ha pasado ninguno de estos asteriscos. Correecho ls *
para ver qué se ejecutará cuando escribasls *
.Puede desmitificar todo el proceso escribiendo en
echo
lugar dels
primero, para ver a qué se expande el comando:Entonces, en este caso, se
ls *
expande als Applications Downloads Documents tmp.html
Entonces no hay cambio. Esto supone que lo está utilizando
bash
como caparazón: la mayoría de las personas lo son y las diferentes capas tienen un comportamiento diferente. Si usaash
orcsh
oksh
orzsh
, puede esperar que las cosas funcionen de manera diferente. Ese es el punto de tener diferentes conchas.Entonces, intentemos algo diferente (todavía con
bash
) para tener una idea de lo que el*
operador globbing ( ) puede hacer por nosotros. Por ejemplo, podemos filtrar por parte del nombre:Y curiosamente, una barra diagonal final es una parte implícita de cualquier nombre de directorio. Por
*/
lo tanto , solo generará los directorios (y enlaces simbólicos a los directorios):Y podemos hacer algunos filtros en múltiples niveles colocando barras en el medio:
Como el
Downloads
directorio no contiene ningún subdirectorio, no termina en la salida. Esto es muy útil solo para examinar los archivos que desea. Yo uso comandos como este todo el tiempo:Esto enumera, si hay alguno, todos los
wp-config.php
archivos que existen en el nivel base delpublic_html
directorio de cualquier usuario . O tal vez para ser más completo:Esto encontrará cualquier
wp-config.php
archivo en lospublic_html
directorios de cualquier usuario o en cualquiera de sus subdirectorios, pero funcionará de manera más eficiente que solofind /home/ -name wp-config.php
porque no examinará nada más que lospublic_html
directorios para cada uno de los usuarios.fuente
bash
como su shell" ← y que el globstar no está habilitado.shopt -s globstar
e inténtalo de nuevo ...set -x
que comenzará a imprimir el comando "real" ejecutado cada vez (desactivar conset +x
).En algunos shells, incluido bash 4.x con la
globstar
opción habilitada,**
se realizará un recursivo glob, descendiendo directorios coincidentes. Los asteriscos adicionales no modifican más esta operación.fuente
ksh93
yzsh
,bash
atraviesa los enlaces simbólicos en la recursión, que generalmente no es deseada.Si desea "sumergirse profundamente", use la opción ls -R (recursiva), o use find, así:
"find" se sumergirá en la parte inferior del árbol de directorios (al igual que 'ls -R'), y tiene muchas más opciones, como enumerar directorios (-type d), solo archivos (-typef) o mostrar archivos que tienen otros características (ningún usuario en / etc / passwd, permisos específicos y mucho más). "find" también es algo más seguro en las secuencias de comandos (debido a reglas de bloqueo inconsistentes entre shells, así como escapes especiales para archivos con guiones, etc.).
el uso de comodines de shell no funcionará solo con un asterisco '*' en los archivos de puntos. Para enumerar solo los archivos de puntos, use:
ls .??*
fuente
Extra * no agrega nivel de profundidad. Pero si lo intentas
- obtendrá una lista de subcarpetas de subcarpetas en carpetas en la carpeta actual ...
fuente
*
s adicionales agregarán nivel de profundidad.bash
con la opción globstar, el shell korn y zsh. Y posiblemente otros, supongo. unix.stackexchange.com/a/62665/14831Mi agarre principal es ese echo ** / *. Ext generalmente ...
Mayo o mayo no: enumere un archivo .ext en el directorio actual
Mayo o mayo no: incluye archivos. *. Ext
En general, preferiría que la expresión global sea '** /' y que pueda dar como resultado una cadena nula (sin subdirectorio). Así es como convierto expresiones globales en la entrada del programa. Por supuesto, me aseguro de que haya comentarios que expliquen esto en ejemplos de uso.
fuente