¿Por qué el comando de tubería "l | grep ”1“ ”obtiene el resultado incorrecto?

13

Como ilustra la imagen, uso lpara obtener el archivo en la carpeta actual. Y luego quiero obtener el archivo con el número 1, así que uso el pipey el grep.

Pero, ¿por qué aparecen el archivo 2y 22? ¿Y cuál es el 1;34m?

$ l
./ ../ 1 11 2 22
$ l | grep "1"
1;34m./ 1;32m../ 1 11 2 22

Actualizar

Ya he alias el comando len mi zshrcarchivo.

 alias lsp="ls"
 alias ll='ls -alF'
 alias la='ls -A'
 alias l='ls -CF'
 alias ls="ls -alh --color"

Y aquí está el resultado del typecomando:

>$ type ls
ls is an alias for ls -alh --color

> $ type l
l is an alias for ls -CF
Sotavento
fuente
44
No publique capturas de pantalla de texto. Copie el texto aquí y aplique el formato de código.
muru
@muru Creo que querías preguntar la salida de publicación de type -a l?
WinEunuuchs2Unix
@ WinEunuuchs2Unix ah, sí.
muru
@Lee, ¿puedo pedirte que publiques la salida del type lscomando por favor? ¿has modificado el lsalias de alguna manera?
Sergiy Kolodyazhnyy
@Serg ya actualizado.
Lee

Respuestas:

27

En primer lugar, lo que intentas hacer l| grep <filename>es malo. No lo hagas Este es el por qué.

l comando es realmente un alias para ls -CF

$ type -a l
l is aliased to `ls -CF'

Por defecto en Ubuntu bash, lses un alias para ls --color=auto. Como Steeldriver señaló en los comentarios, --color=autose supone que apaga la coloración. En su caso específico, tiene alias ls="ls -alh --color"y alias l="ls -CF", que básicamente termina siendo ls -alh --color -CF. Esta combinación particular de interruptores aún envía salidas coloreadas a través de una tubería. Por ejemplo:

$ ls -alh --color -CF ~/TESTDIR | cat -A                                                                                 
^[[0m^[[01;34m.^[[0m/  ^[[01;34m..^[[0m/  1.txt  2.txt  3.txt  out.txt$

Observe cómo los directorios .y ..tienen las mismas secuencias de escape.

Qué significa todo esto

Esto significa que lgenerará una lista coloreada de archivos según el tipo de archivo. El problema es que la coloración ocurre con el uso de secuencias de escape . Eso es lo 1:34mque son las cosas: son secuencias de escape para colores específicos.

El problema principal es que el análisis a lsmenudo conduce a resultados incorrectos y desastres en los scripts, simplemente porque lspermite secuencias de escape como se explicó anteriormente y otros caracteres especiales. Consulte este artículo para obtener más información: http://mywiki.wooledge.org/ParsingLs

Lo que deberías estar haciendo:

Use el findcomando:

bash-4.3$ ls
1.txt  2.txt  3.txt  out.txt
bash-4.3$ find . -maxdepth 1 -iname "*1*"
./1.txt

Podría hacer algo como esto con shell glob y el [[comando de prueba moderno :

bash-4.3$ for file in * ;do if [[ "$file" =~ "1"  ]] ;then echo "$file" ;fi ; done
1.txt

O tal vez use python, que tiene capacidades de manejo de nombre de archivo mucho mejores que bashsolo

bash-4.3$ python -c 'import os;print [f for f in os.listdir(".") if "1" in f ]'
['1.txt']

Si no hay necesidad de procesar la salida ls, también lspuede hacer el trabajo de forma simple . (Recuerde, esto es solo para ver la lista de archivos, no para pasarlo a otro programa para tratar el texto de salida)

bash-4.3$ ls *1*
1.txt
Sergiy Kolodyazhnyy
fuente
2
Creo que la salida solo se coloreará en una tubería si --color=alwaystambién se especifica, ya sea como parte del alias para lo en un alias anterior para lssí mismo (reemplazando el valor predeterminado alias ls='ls --color=auto').
steeldriver
@steeldriver Buen punto, pero ¿no es eso lo que lsen bash es por defecto? type lsme da que es un alias parals --color=auto
Sergiy Kolodyazhnyy
1
Sí, ese es el valor predeterminado, pero autodesactiva el color en una tubería AFAIK. Para ver secuencias de color ANSI, debe haberse cambiado a --color=always, ya sea en el lsalias o en el lalias
steeldriver
Oh, ya veo lo que quieres decir. Eso es muy raro
Sergiy Kolodyazhnyy
@steeldriver Entonces solicité a OP que publicara sus alias, y aparentemente lo que tienen, es decir ls --color, no impide la coloración (también lo probé). Actualicé mi respuesta en consecuencia
Sergiy Kolodyazhnyy
6

Sus ly lscomandos se configuran como alias.

Cuando los ejecuta, canaliza la salida a través de grep "1"(usando |) cada línea de pantalla donde 1aparece, con el 1color rojo.

Debido a que los nombres de archivo ., .., 2y 22aparecen en la misma línea de la pantalla, que son mostradas con greptambién, pero no aparecen en rojo que muestra grepcoincidencias.

El :34mes una secuencia de escape para un color que no se pinta correctamente. Basado en su pregunta revisada con la salida de type -a ly type -ase puede reproducir en mi sistema. Tenga en cuenta que debe cambiar su alias de --colora --color=auto:

Salida de color

color ls

WinEunuuchs2Unix
fuente
Las 1:34mcosas no son corrupción, son secuencias de escape utilizadas para colorear el texto. Ver mi respuesta en esa parte;)
Sergiy Kolodyazhnyy
@Serg Gracias. He revisado según la pregunta revisada de OP con alias.
WinEunuuchs2Unix
1

En su prueba, estaba llamando a su lsalias, por lo tanto, al 1;34mruido similar que proviene de la coloración, y dado que la tubería |recibe todo esto en la misma línea, grepcoincide con el archivo 1de esa línea y, en consecuencia, imprime esta línea. Esto es lo que ves en la pantalla.

Cuando está haciendo cosas así, siempre es bueno volver al comando del sistema con 1 resultado por línea.

Para deshacerse de los alias, simplemente escriba \lsy use la opción -1para imprimir resultados separados por saltos de línea.

$ \ls -1 | grep "1"
1
11

Nota: el método de barra invertida funciona con cada comando, \commandsolo llama al comando de sistema sin alias.

pilko
fuente