Why the pipe command "l | grep "1" " get the wrong result?
As the picture illustrates, I use l
to get the file in the current folder. And then I want to get the file with number 1
, so I use the pipe
and the grep
.
But why the 2
and 22
file show out? And what is the 1;34m
?
$ l
./ ../ 1 11 2 22
$ l | grep "1"
1;34m./ 1;32m../ 1 11 2 22
Update
I have already alias the command l
in my zshrc
file.
alias lsp="ls"
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'
alias ls="ls -alh --color"
And here is the result of the type
command:
>$ type ls
ls is an alias for ls -alh --color
> $ type l
l is an alias for ls -CF
First of all, what you're trying to do , l| grep <filename>
is bad. Don't do it. Here's why.
l
command is really an alias to ls -CF
$ type -a l
l is aliased to `ls -CF'
By default in Ubuntu's bash
, ls
is an alias to ls --color=auto
. As steeldriver pointed out in the comments --color=auto
is supposed to turn off colorization. In your specific case , you have alias ls="ls -alh --color"
and alias l="ls -CF"
, which basically ends up being ls -alh --color -CF
. This particular combination of switches still sends colorized output over a pipe. For example:
$ ls -alh --color -CF ~/TESTDIR | cat -A
^[[0m^[[01;34m.^[[0m/ ^[[01;34m..^[[0m/ 1.txt 2.txt 3.txt out.txt$
Notice how the .
and ..
directories have same escape sequences.
What does this all mean
This means that l
will output colorized list of files according to file type. Problem is that colorization happens with the use of escape sequences. That's what 1:34m
things are - they're escape sequence for specific colors.
The main problem is that parsing ls
often leads to wrong output and disasters in scripts, simply because ls
allows escape sequences like explained earlier and other special characters. See this article for more info: http://mywiki.wooledge.org/ParsingLs
What you should be doing:
Use find
command :
bash-4.3$ ls
1.txt 2.txt 3.txt out.txt
bash-4.3$ find . -maxdepth 1 -iname "*1*"
./1.txt
You could do something like this with shell glob and modern test [[
command:
bash-4.3$ for file in * ;do if [[ "$file" =~ "1" ]] ;then echo "$file" ;fi ; done
1.txt
Or maybe use python, which has far better filename handling capabilities than bash
alone
bash-4.3$ python -c 'import os;print [f for f in os.listdir(".") if "1" in f ]'
['1.txt']
If there's no need to process the output of ls
, simple globbing with ls
can do the work, too. ( Remember, this is only for viewing list of files, not for passing it to another program to deal with the output text)
bash-4.3$ ls *1*
1.txt
Your l
and ls
commands are setup as aliases.
When you run them piping the output through grep "1"
(using |
) each screen line where 1
appears is displayed, with the 1
colored red.
Because file names .
, ..
, 2
and 22
appear on the same screen line, they are output by grep
as well but do not appear in red which shows grep
matches.
The :34m
is an escape sequence for a color that doesn't paint properly. Based on your revised question with the output of type -a l
and type -a
it can be reproduced in my system. Please note you should change your alias from --color
to --color=auto
: