grep the lines of file using for loop - linux

There is a file and each line shows the different file paths.
```
my_file
/the/first/path/file1
/the/second/path/file2
....
```
I want to use for loop to find a string in each file.
```
for i in $(cat my_file); do cd "$i"; done | grep -w string "$i"
```
But this seems not working for me. I am getting this for all file directory
-bash: cd: /the/first/path/file1: No such file or directory
What am I doing wrong? Thanks in advance for any help

No need for a for loop, use xargs:
xargs -a my_file -d '\n' grep -h -w string
Note #1: I added the -h option (GNU extension) so that the filenames are not added by grep in the output (like in your command).
Note #2: since you are using Linux and Bash, I'm assuming GNU xargs. If your xargs does not understand the -a option, then use this instead:
< my_file xargs -d '\n' grep -h -w string

Related

Search & replace on all files in server

I want to search for this line:
<script type="text/javascript" src="//example.com/file.php?zoneid=112" async data-cfasync="false"></script>
And remove it/replace it with blank.
What command line could I run on linux to search and replace this term on all files on the server?
I have used a combination of grep and sed
string_to_replace='<script type="text/javascript" src="//example.com/file.php?zoneid=112" async data-cfasync="false"></script>'
First just run the grep statement to make sure you are matching the right string and file. If everything looks good, then run the following command;
grep -Inr "${string_to_replace}" | while read line; do filename=`echo $line | cut -d ":" -f 1`; line_no=`echo $line | cut -d ":" -f 2`; sed "${line_no}d" -i $filename; done
In grep, -I will ignore binaries, -n will print the line number and -r will do a recursive search.
Let me know if something is not working.
You can use sed with regex and command d over the file:
sed -i '/regex/d' file
Next construction could help you to pass filenames with find to sed:
find . | xargs sed -i '/regex/d'
Be careful with debugging. :)

How to get only filenames without Path by using grep

I have got the following Problem.
I´m doing a grep like:
$command = grep -r -i --include=*.cfg 'host{' /omd/sites/mesh/etc/icinga/conf.d/objects
I got the following output:
/omd/sites/mesh/etc/icinga/conf.d/objects/testsystem/test1.cfg:define host{
/omd/sites/mesh/etc/icinga/conf.d/objects/testsystem/test2.cfg:define host{
/omd/sites/mesh/etc/icinga/conf.d/objects/testsystem/test3.cfg:define host{
...
for all *.cfg files.
With exec($command,$array)
I passed the result in an array.
Is it possible to get only the filenames as result of the grep-command.
I have tried the following:
$Command= grep -l -H -r -i --include=*.cfg 'host{' /omd/sites/mesh/etc/icinga/conf.d/objects
but I got the same result.
I know that on the forum a similar topic exists.(How can I use grep to show just filenames (no in-line matches) on linux?), but the solution doesn´t work.
With "exec($Command,$result_array)" I try to get an array with the results.
The mentioned solutions works all, but I can´t get an resultarray with exec().
Can anyone help me?
Yet another simpler solution:
grep -l whatever-you-want | xargs -L 1 basename
or you can avoid xargs and use a subshell instead, if you are not using an ancient version of the GNU coreutils:
basename -a $(grep -l whatever-you-want)
basename is the bash straightforward solution to get a file name without path. You may also be interested in dirname to get the path only.
GNU Coreutils basename documentation
Is it possible to get only the filenames as result of the grep command.
With grep you need the -l option to display only file names.
Using find ... -execdir grep ... \{} + you might prevent displaying the full path of the file (is this what you need?)
find /omd/sites/mesh/etc/icinga/conf.d/objects -name '*.cfg' \
-execdir grep -r -i -l 'host{' \{} +
In addition, concerning the second part of your question, to read the result of a command into an array, you have to use the syntax: IFS=$'\n' MYVAR=( $(cmd ...) )
In that particular case (I formatted as multiline statement in order to clearly show the structure of that expression -- of course you could write as a "one-liner"):
IFS=$'\n' MYVAR=(
$(
find objects -name '*.cfg' \
-execdir grep -r -i -l 'host{' \{} +
)
)
You have then access to the result in the array MYVAR as usual. While I while I was testing (3 matches in that particular case):
sh$ echo ${#MYVAR[#]}
3
sh$ echo ${MYVAR[0]}
./x y.cfg
sh$ echo ${MYVAR[1]}
./d.cfg
sh$ echo ${MYVAR[2]}
./e.cfg
# ...
This should work:
grep -r -i --include=*.cfg 'host{' /omd/sites/mesh/etc/icinga/conf.d/objects | \
awk '{print $1}' | sed -e 's|[^/]*/||g' -e 's|:define$||'
The awk portion finds the first field in it and the sed command trims off the path and the :define.

Replace string using grep and sed

I have bunch of files in a directory,
I need to change prefix of lines in file like "AB_" to "YZ_"
how can i do it?
i have used grep and sed like,
grep -nr "AB_" ./ | xargs -0 sed -i 's/AB_/YZ_/g'
but giving error,
: File name too long
example string in a file are: Hello AB_WORLD! and Hello WORLD_AB!
Thanks.
sed will take multiple files as arguments, so this should work:
sed -i '/AB_/s//YZ_/g' *
(Note that -i is non-standard)
You mean grep -lr not grep -nr
-l gives you the file name; -n gives you the matching line with line number prepended
I like Perl for this one:
The -i option will save the original file with a.bak extension.
$ perl -i.bak -pe 's/^AB_/YZ_/' *.txt
grep -lr "AB_" ./ | while read file
do
echo "Change file $file ..."
sed -i 's/AB_/YZ_/g' ${file}
done
sed one-liner answer
Find php files in the directory containing string "foo" and replace all occurences with "bar"
grep -l foo *.php | xargs sed -i '' s/foo/bar/g
To recurse through directories
grep -rl foo * | xargs sed -i '' s/foo/bar/g
(just done successfully on 8100 files)
grep -rl bar * | wc -l
8102

grep for line containing jboss- until next /

I am trying to grep out of a init script status, just the jboss directory.
So in the stdout there is this line:
JBOSS_CMD_START = ulimit -c 2500000; cd /home/blah; /apps/jboss-eap-5.1.2/jboss-as/bin/run.sh -c jboss-blahtest -b 1.1.2.3 -Djboss.messaging.ServerPeerID=1
And out of that, I am trying to grep just the directory, up until /jboss-as, so the results would be:
/apps/jboss-eap-5.1.2/jboss-as/
The problem is the jboss version can be a number of things, so I need to get from /apps/jboss- to /jboss-as/
grep -oE '/apps/jboss-eap-[^/]+/jboss-as/'
One option
grep -Eo '/[^[:space:]]+jboss-as/'
grep -oE '\S+/jboss-as/ should do it.

grep command working in testdir but not in "real" directory

I just thought I had found my solution because the command works in my test directory.
grep -H -e 'author="[^"].*' *.xml | cut -d: -f1 | xargs -I '{}' mv {} mydir/.
But using the command in the non-test-direcory the command did not work:
This is the error message:
grep: unknown option -- O
Usage: grep [OPTION]... PATTERN [FILE]...
Try `grep --help' for more information.
Not even this worked:
$ grep -H author *.xml
or this:
$ grep -H 'author' *.xml
(same error message)
I suspect it has some relation to the file names or the amount of files.
I have almost 3000 files in the non-test-directory and only 20 in my test directory.
In both directories almost all file names contain spaces and " - ".
Some more info:
I'm using Cygwin.
I am not allowed to change the filenames
Try this (updated):
grep -HlZ 'author="[^"].*' -- *.xml | xargs -0 -I {} mv -- {} mydir/
EXPLANATION (updated)
In your "real" directory you have a file with name starting with -O.
Your shell expands the file list *.xml and grep takes your - starting filename as an option (not valid). Same thing happens with mv. As explained in the Common options section of info coreutils, you can use -- to delimit the option list. What comes after -- is considered as an operand, not an option.
Using the -l (lowercase L) option, grep outputs only the filename of matching files, so you don't need to use cut.
To correctly handle every strange filename, you have to use the pair -Z in grep and -0 in xargs.
No need to use -e because your pattern does not begin with -.
Hope this will help!

Resources