I've a bash script that's supposed to go over all the filenames and print them only those that contain a certain letter (let's say it's 'o').
What I've done:
command=`ls -l`
for file in $command
do
if $file | grep 'o' ;
then
echo "$file"
fi
done
This doesn't work, it says 'command not found' on the line:
if $file | grep 'o' ;
I looked up several other answers here and they're doing the same thing I am, i.e. no parentheses for the if-statement, same syntax etc.
What am I overlooking?
Best Answer
$file | grep -o
executes the command specified by the value offile
and pipes its output togrep
. But that's clearly not what you wanted.If you want to list files that contain
o
You meant the value of
file
to be an input file forgrep
, not a command to execute. So you need an input redirection, not a pipe.grep
reads from standard input if it doesn't receive a file name on its command line. You can also pass a file name on the command line; this does the same thing.For why the double quotes, and why the
--
in the second method, see Why does my shell script choke on whitespace or other special characters?To suppress the output from
grep
, use the-q
option, or redirect the output to/dev/null
.or
Another problem with your script is that
command=`ls -l`
sets the variablecommand
to the output of the commandls -l
, which is not a list of file names. If you recall Why does my shell script choke on whitespace or other special characters?, you'll remember that it's impossible to store a list of file names in a string variable: all the file names are jumbled together. Here, it's even worse: there's junk like permissions, dates, etc. The way to get a list of file names in a shell script is to use a wildcard pattern.All of this is equivalent to
If you want to list files whose name contains
o
This feature is built into the shell, with wildcard patterns. The pattern
*o*
matches file names that containo
, so to list them, you only needThe
--
is necessary in case one of the file names begins with-
, otherwisels
might interpret the file name as an option.If this is a learning exercise on the use of
grep
, and you want to pass the file name as input togrep
, you need to use theecho
command.The
echo
command might mangle some file names. To be safe, useprintf
. For more on this, and on the use of double quotes, see Why does my shell script choke on whitespace or other special characters?As above, don't parse the output of
ls
.If your file names don't contain any newlines, you could reduce this to.
Once again, the loop is pointless here and you can just use
to print the matching file names on separate lines. The use of
grep
would only be justified if you needed a regular expression that your shell's wildcard patterns aren't powerful enough to express.