find with grep not working inside shell script - shell

I am using the below command to find the file names and it works fine when execute from command line:
$AIX->: find . | xargs grep -l "BE00036"
./6281723219129
$AIX->:
But the same command is not working when execute from shell script(ksh):
$AIX->: ksh test.ksh
**find: bad option -l**
part of my code is:
Var="find . | xargs grep -l \"BE00036\"
print `$Var`

If you want to assign the output of a command to a variable, you can do
Var="$(find . | xargs grep -l \"BE00036\")"
print "$Var"

This below one works for me:
var=`find . | xargs grep -l 'BE00036'`
echo "$var"

Related

Since establishes an alias of the following command?

Hello I am trying to establish in the following alias with gitbash and cannot :
alias dirpwd='$(`pwd | xargs dirname | xargs basename -a`)' && echo -e $dirpwd;
The output is :
bash: c: command not found
Why?
Thanks all !!
What happens:
Backticks and $() work in the same way. The command inside them gets executed and the resulting output is treated as if you typed it in directly.
Assume you are in /top/c/bottom.
The part pwd | xargs dirname | xargs basename -a inside the backticks has output c.
Bash replaces the backtick part with its output, resulting in the command $(c).
Now bash tries to execute the command inside $(...) but c is not a command, hence the error bash: c: command not found.
First Fix:
I guess you just want to write
alias dirpwd="pwd | xargs dirname | xargs basename -a"
Bug:
There is a hidden bug. xargs splits at spaces and may pass multiple arguments to dirname and basename.
Example: Assume you you are in /top/a b c/. xarg creates the following command and output
dirname "/top/a" "b" "c/"
/top
.
.
Second Fix:
Use $() instead of xargs.
alias dirpwd='basename "$(dirname "$PWD")"'
Try how an solution is :
alias dirpwd="pwd | xargs dirname | xargs basename -a"

file and number of lines matching

I am trying to count lines in the files which matches to the given pattern. now the problem is it gives me only the number of lines. How can i get the file location or name along with number of matched lines?
command i am using now is
for i in $(find . -name 'foo.txt' | sed 's/\.\///g');
do
grep -l && -c '^>' $i;
done
so output i am expecting is like "file location/name number of lines matching"
grep can show you the file name if you specify it as a command-line argument. You can use xargs to invoke grep for each batch of filenames. It'll read the names from standard input and use them as command line arguments for grep.
find . | xargs grep -cH '^>'
Using your find command:
find . -name 'foo.txt' | sed 's/\.\///g' | xargs grep -cH '^>'
You capture the number of lines matching in a variable and test it:
n=$(grep -c '^>' "$i")
(( n > 0 )) && echo "$i:$n"
Actually, you don't even need the test: grep exits unsuccessfully if no matches found, so
n=$(grep -c '^>' "$i") && echo "$i:$n"
Actually, that's too much work. With GNU grep at least, use the -H option. A demo with a file I have lying around:
$ grep -c zero note.xml
16
$ grep -Hc zero note.xml
note.xml:16

Shell command xargs & sed doesn't work

I just want to batch modify the suffix of the files,but it doesn't work!
The command line I used as below:
ls *html | xargs -I{} echo "\`echo {} | sed 's/html/css/g'\`"
However, when I just used ls *html,it shows:
file1.html file2.html file3.html file4.html file5.html
used ls *html | sed 's/html/css/g',it shows as I expected!
like this:
file1.css file2.css file3.css file4.css file5.css
I work on Mac OS. Could anyone give me some suggestions?
Thans in advance.
Because the backquotes are in double quotes, it gets executed immediately by the shell and not by xargs on each file.
The result is the same as
ls *html | xargs -I{} echo "{}"
However, if you use single quotes, you run into other troubles. You end up having to do something like this:
ls *html | xargs -I{} sh -c 'echo `echo {} | sed '\''s/html/css/g'\''`'
but it gets to be a mess, and we haven't even got to the actual renaming yet.
Using a loop is a bit nicer:
for file in *html; do
newname=${file%html}css
mv "$file" "$newname"
done
Using GNU Parallel:
ls *html | parallel echo before {} after {.}.css

Search file name using a variable and replace with another variable

I have search string in one variable ($AUD_DATE) and replace string in another variable ($YEST_DATE). I need to search file name in a folder using $AUD_DATE and then replace it with $YEST_DATE.
I tried using this link to do it but its not working with variables.
Find and replace filename recursively in a directory
shrivn1 $ AUD_DATE=140101
shrivn1 $ YEST_DATE=140124
shrivn1 $ ls *$AUD_DATE*
NULRL.PREM.DATA.CLRSFIFG.140101.dat NULRL.PREM.DATA.CLRTVEH.140101.dat
shrivn1 $ ls *$AUD_DATE*.dat | awk '{a=$1; gsub("$AUD_DATE","$YEST_DATE");printf "mv \"%s\" \"%s\"\n", a, $1}'
mv "NULRL.PREM.DATA.CLRSFIFG.140101.dat" "NULRL.PREM.DATA.CLRSFIFG.140101.dat"
mv "NULRL.PREM.DATA.CLRTVEH.140101.dat" "NULRL.PREM.DATA.CLRTVEH.140101.dat"
Actual output I need is
mv "NULRL.PREM.DATA.CLRSFIFG.140101.dat" "NULRL.PREM.DATA.CLRSFIFG.140124.dat"
mv "NULRL.PREM.DATA.CLRTVEH.140101.dat" "NULRL.PREM.DATA.CLRTVEH.140124.dat"
Thanks in advance
Approach 1
I generally create mv commands using sed and then pipe the output to sh. This approach allows me to see the commands that will be executed beforehand.
For example:
$ AUD_DATE=140101
$ YEST_DATE=140124
$ ls -1tr | grep "${AUD_DATE}" | sed "s/\(.*\)/mv \1 \1_${YEST_DATE}"
Once you are happpy with the output of the previous command;repeat it and pipe it's output to sh, like so:
$ ls -1tr | grep "${AUD_DATE}" | sed "s/\(.*\)/mv \1 \1_${YEST_DATE}" | sh
Approach 2
You could use xargs command.
ls -1tr | grep ${AUD_DATE}" | xargs -I target_file mv target_file target_file${YEST_DATE}

bash: Script arguments ${1} interfering with xargs' ${1} inside script

Long story short, I have a script chunk that looks like this:
cd ${1} # via command-line argument
find . -name "output*.txt" | xargs cat ${1} | grep -v ${filter} > temp.txt
I essentially got to this point buy building the find ... line in the command line, then pasting it into my script, then adding the cd command to make it easy to reuse this script in a wrapper that will run this script on a large set of directories. Anyway ...
The problem is that cd and xargs use the same ${1} variable, which sort of makese
I know that I can drop the ${1} argument from xargs, and I can probably rewrite the find command to not need xargs at all, but my question remains:
Is there a way to "reset" ${1} after I use it for cd so that xargs doesn't
I'm not familiar with a version of xargs that uses ${1} as a default replacement string, but the following should work:
find . -name "output*.txt" | xargs -I '{}' cat '{}' | grep -v ${filter} > temp.txt
Your use of find + xargs suffers from The separator problem https://en.wikipedia.org/wiki/Xargs#Separator_problem
Here is a solution that does not have that problem. It uses GNU Parallel:
find . -name "output*.txt" |
parallel cat {} |
grep -v ${filter} > temp.txt
It takes literally 10 seconds to install GNU Parallel:
$ (wget -O - pi.dk/3 || lynx -source pi.dk/3 || curl pi.dk/3/ || \
fetch -o - http://pi.dk/3 ) > install.sh
$ sha1sum install.sh | grep 883c667e01eed62f975ad28b6d50e22a
12345678 883c667e 01eed62f 975ad28b 6d50e22a
$ md5sum install.sh | grep cc21b4c943fd03e93ae1ae49e28573c0
cc21b4c9 43fd03e9 3ae1ae49 e28573c0
$ sha512sum install.sh | grep da012ec113b49a54e705f86d51e784ebced224fdf
79945d9d 250b42a4 2067bb00 99da012e c113b49a 54e705f8 6d51e784 ebced224
fdff3f52 ca588d64 e75f6033 61bd543f d631f592 2f87ceb2 ab034149 6df84a35
$ bash install.sh
Watch the intro videos to learn more: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
the utility xargs is just to manage the number of arguments and there braces act as a placeholder for the arguments or filename {}.
i did simulate the wrapper you have and had the same issue the pathname passed as ${1} to my function was picked up by xargs ...... but this is how shell works , actually the shell would just substitute/expand all the variables and stuff to make the commands complete before execution
the utility arnt coded to take care of this by themselves , they just dont do that ......
example :
echo * ;
here the shell would expand * and replace it with all the filenames in the current directory and pass them to the echo utility as argument # before execution of the command echo *
likewise in your case the shell is expanding the ${1} to the pathname value you had passed before executing the command ..... thats why you got what you had.
Solution : you could just use the braces (empty of course) or better just drop them ....... it works fine for me .....
find . -iname "*${filename}*" | xargs ls -l | more commands ....;
hope this helps .

Resources