0

We want to grep the corresponding files that including some fixed strings, and then output those files just only in ls -l format.
For example:
A) the following method with multiple -exec output both the grep and ls -l.

# 
# 
# find /usr/bin -type f -exec grep -Eil '#\!\/usr\/bin\/csh' {} \; -exec ls -l  {} \; >scripts_csh_list 2>&1
# 
# 
# 
# cat scripts_csh_list      
/usr/bin/which
-r-xr-xr-x    1 bin      bin            1191 Sep 06 2007  /usr/bin/which
#  
#  

B) But we want to the better method output only with ls -l ... , and then we failed via sh -c 'grep ... {}'
Notes: all the following different combined commands for the find -exec ... output the same failed result.

#                                                                                                                
# 
# find /usr/bin -type f -exec sh -c 'grep -Eil '\/usr\/bin\/csh' {} && ls -ltr  {}' \; >scripts_csh_list 2>&1t
#  
# 
# tail -6 scripts_csh_list
grep: 0652-033 Cannot open {}.
grep: 0652-033 Cannot open {}.
grep: 0652-033 Cannot open {}.
grep: 0652-033 Cannot open {}.
grep: 0652-033 Cannot open {}.
grep: 0652-033 Cannot open {}.
# 
# 
# 
# find /usr/bin -type f -exec sh -c ' grep -Eil '\/usr\/bin\/csh' {} '  \; >scripts_csh_list 2>&1  
# 
# 
# tail -6 scripts_csh_list                                                                         
grep: 0652-033 Cannot open {}.
grep: 0652-033 Cannot open {}.
grep: 0652-033 Cannot open {}.
grep: 0652-033 Cannot open {}.
grep: 0652-033 Cannot open {}.
grep: 0652-033 Cannot open {}.
# 
# 
# find /usr/bin -type f -exec sh -c ' grep -Eil '\/usr\/bin\/csh' "{}" '  \; >scripts_csh_list 2>&1  
# 
# 
# tail -6 scripts_csh_list                                                                         
grep: 0652-033 Cannot open {}.
grep: 0652-033 Cannot open {}.
grep: 0652-033 Cannot open {}.
grep: 0652-033 Cannot open {}.
grep: 0652-033 Cannot open {}.
grep: 0652-033 Cannot open {}.
# 
# 
# 
# find /usr/bin -type f -exec sh -c " grep -Eil '\/usr\/bin\/csh' {} "  \; >scripts_csh_list 2>&1  
# 
# 
# tail -6 scripts_csh_list                                                                         
grep: 0652-033 Cannot open {}.
grep: 0652-033 Cannot open {}.
grep: 0652-033 Cannot open {}.
grep: 0652-033 Cannot open {}.
grep: 0652-033 Cannot open {}.
grep: 0652-033 Cannot open {}.
# 
# 
# 
# find /usr/bin -type f -exec sh -c " grep -Eil '\/usr\/bin\/csh' {} "  \; >scripts_csh_list 2>&1  
# 
# 
# tail -6 scripts_csh_list                                                                         
grep: 0652-033 Cannot open {}.
grep: 0652-033 Cannot open {}.
grep: 0652-033 Cannot open {}.
grep: 0652-033 Cannot open {}.
grep: 0652-033 Cannot open {}.
grep: 0652-033 Cannot open {}.
# 
# 
lylklb
  • 303

2 Answers2

3

There is a lot of what appears to be unnecessary quoting and escaping in the original. While I don't have any csh scripts in /usr/bin, I was able to find bash scripts and get the ls output you appear to want with the following:

find /usr/bin -type f -exec grep -q '#!/usr/bin/bash' {} \; -exec ls -l {} \; 2> /dev/null

(I verified this by running without the second -exec, e.g.,

find /usr/bin -type f -exec grep -q '#!/usr/bin/bash' {} \; 2> /dev/null

and inspecting the results.)

For a slightly different output listing, you could also do

find /usr/bin -type f -exec grep -q '#!/usr/bin/bash' {} \; -ls 2> /dev/null

where find stats each matching file itself, directly, and returns ls-like results.

I piped errors to /dev/null simply to make things more readable as I was testing; for similar reasons, I didn't pipe the output to a file.

Note that I am using bash as my shell, so wrapping the grep expression in single quotes ('...') was sufficient to prevent any interpretation of its contents (not that there is much to worry about, forward slashes (/) aren't special for the shell, at least not for bash. If you are using a shell with different quoting rules, YMMV.

As to the command, unless you use the -o option, find will AND together all criteria, so this runs ls -l ONLY on regular files (the type f you included) that pass the grep check. As noted in the comments on your question, grep -q likely does what you want, which is simply determine if the file in question ({}) matches or not.

EDIT: As noted in the comments, if the user's shell is csh, they will need to escape the ! in the grep expression: '#\!/usr/bin/bash' should work.

0

Finally we did the following correct method via sh -c 'grep ... ' with find -exec commands. Thanks all!

# find /usr/bin -type f -exec sh -c ' grep -q ''\#'\!/usr/bin/csh'  "$1" && ls -l "$1" ' sh {} \; >scripts_csh_list 2>&1

head -3 scripts_csh_list

-r-xr-xr-x 1 bin bin 1191 Sep 06 2007 /usr/bin/which

AdminBee
  • 22,803
lylklb
  • 303