greping for a value != *.file extension - bash

Not 100% on how to go about this.
Basically my app creates two file outputs.
file
file.ext
when searching through the directory it always returns both files. I wish only to work with
file
how can I do a grep for just the file? Or is grep even the correct command?
!grep *.ext
pseudo code ^

Why not just:
grep foobar file
or if you want to search your directory
find . -name 'file' | xargs -r grep boofar

You can try using grep 'file$', i.e. select lines ending with file and nothing after that. Alternatively you can use grep -v to invert results.
# (echo "file"; echo "file.txt") | grep file$
file
# (echo "file"; echo "file.txt") | grep -v .ext
file

I have no idea what you are trying to do with grep, but if you want to check whether a file exists, you do simply this:
if [ -r /some/path/file ]; then
echo "File is readable."
fi

Grep has a -v flag that inverses the meaning (looks for lines that do not contain the pattern):
ls /your/directory | grep -v '\.ext$'
This will exclude every filename ending with .ext.

Try
grep -v option
-v do the inverse match
For details do $ man grep

To generate a list of all files that do not match a pattern, use -not in find. So you want:
find . -not -name '*.ext'

Related

complex grep show file name and lines below last match

I have a shell command to grep backward the match of "___", and I need a way to view +two lines below this match, as well as append the file name to the start of the grep output.
for f in $(find . -name "*.log"); do tac $f | grep "___" | head -n 1; done
I have tried adding -A 2 but that does not return lines below what is returned, and I tried adding file /dev/null after grep to get it to print file name but I get an error
for f in $(find . -name "*.log"); do tac $f | grep "___" file /dev/null | head
-n 1; done
grep: file: No such file or directory
Adding -A 2 to grep wouldn't work because you're piping it to head -n 1.
Since you only want a single match you can add -m 1 to tell grep to stop after 1 match instead of piping into head -n 1
Since you've reversed the file you may want to use -B 2 (-B for before rather than -A for after).
After matching you may want to reverse again with tac so the match resembles the actual file contents.
As for adding the file name: you already have it in $f, just echo it.
All together something like:
for f in $(find . -name "*.log"); do echo "${f}:"; tac ${f} | grep -m 1 -A 2 "___" | tac; done
When you added file /dev/null to grep you're giving it more parameters to search which is why you got an error that file wasn't found because you don't have a file named file in your path. I believe this trick won't work when you're piping input into grep because providing files to grep will cause grep to ignore the piped input.

Display configuration files in /etc that contain numbers in their names (using grep)

Task (12) from here.
Using grep I could solve this task as following:
grep --no-message -l [[:alnum:]] /etc/* | grep [[:digit:]]
Similar results were obtained:
ls -o /etc/ | grep ^- | awk '{print $8}' | grep [[:digit:]]
But I want to read all files under each directory, recursively. And this is what I could do:
grep --no-message -lR [[:alnum:]] /etc/* | grep [[:digit:]]
Also how this task can be solved today? Is this a correct way? What kind of additional solutions you can offer to solve this task?
You shouldn't be using to grep just to get file names. i.e. instead of what I think you are trying to do with
grep --no-message -l [[:alnum:]] /etc/*
You can just do
echo /etc/*
Since the goal is to list files with numbers, you can use a glob like:
echo /etc/*[[:digit:]]*
If you want to do this recursively you can do it in bash like:
shopt -s globstar
echo /etc/**/*[[:digit:]]*
Or you can use find:
find /etc -name '*[[:digit:]]*'
You can use find:
find /etc -type f -name \*[[:digit:]]\*
Please note that this command lists only files with digits in names, not the full paths. For the latter use a different filter:
find /etc -type f -path \*[[:digit:]]\*
Grisha and Andrey have given perfect answers. However, if you are looking for a solution that does use grep, here it is.
while read -r filepath; do
# grep for digits in the basename so that we choose only those
# files that have a digit in them, not in any parent directory name
if grep -q '[[:digit:]]' <<< "$(basename $filepath)"; then
echo "$filepath"
fi
done < <(find /etc -type f -print)
It's not efficient at all.
If the task is to have a pure grep solution, then here it is:
grep -laR . /etc | grep '^.*/[^/]*[[:digit:]][^/]*$'
The regular expression:
^...$ cover the full line;
.*/[^/]*...[^/]* look only for the file name.

How to get the grep command to search a specified directory?

I am trying to create a bash command that uses grep to search arguments in a specified directory. How would I do this. At the moment it only searches for the current directory. I have tried the following but it doesn't work:
ls $directoryName -l | grep "$1"
I'm sure there's a better way do do this but
ls -lah $directoryName > /usr/tmp/test
grep $1 /usr/tmp/test
rm /usr/tmp/test
Edit: You might have better luck using find though.
find $directoryName -name $1
Working example:
grep -e "Exec" /usr/share/applications/*
The following example will search recursively (including in sub-folders and hidden files) for an argument or pattern in a literal way (it will search for '$1' literally, not allowing substitution):
grep -re '$1' /folder/folder
Now, if you want to search for the value of the argument, then the code below would allow for substitution and do that:
grep -re "$1" /folder/folder

How to know file name from a pipeline of commands

I search for some text in some file list. I have the following command to print these lines:
ls -1 *.log | xargs tail --lines=10000 | grep text_for_search
The command output contains all of occurrences of text_for_search, but it hasn't information from which file the occurrences are. How to modify the command to provide this information too?
Actually log files are gigabytes in size, so it's essential to use tail --lines=10000 for each of them
You could just use a loop instead, which will keep track of the file name for you:
for file in *.log; do
if tail --lines=-10000 "$file" | grep -q text_for_search; then
echo "$file"
fi
done
The -q switch to grep suppresses the output, returning a 0 (success) exit code if the pattern is matched.
You can use find command:
find . -name "*.log" -exec grep text_for_search '{}' \;
grep will output filename and matched line. If you just need filenames - add -l switch to grep command.
'{}' - macro used for matched file name substitution in find's -exec command,
\; indicates end of arguments for command, called by exec
Replace your tail command with:
awk '{v[NR]=$0}END{for(i=NR-10000;i<=NR;i++)print FILENAME,v[i]}'
This above is just the replacement of the tail command except it adds a file name in the begining of each line.
You must avoid parsing ls output and use shell's for loop to iterate through all *.log files:
for f in *.log; do
awk -v c=$(wc -l < "$f") 'NR>c-10000 && /text_for_search/{print FILENAME ":" $0}' "$f"
done
EDIT:
You can use awk to search through all *.log files:
awk 'NR>=10000 && /text_for_search/ {print FILENAME ":" $0}' *.log

Grep and find the Matching FileNames

I have a txt file which has list of Prefix Id's , I need to take that and match it against the source directory and get the matching file names and build a list.
Im currently using the below code to achieve this , but im getting only the file for last file name in the list
set -A flist $(find $1 -name "*.csv" | grep "`cat ${tempfile}.txt`"
There are some 10 matching files but this command returns only the last file , any help would be appreciated
$ cat prefixes.txt
foo_[^/]*$
bar_[^/]*$
$ find
.
./blah
./foo_1.txt
./bar_3.txt
./bar_4.txt
./quux_6.txt
./quux_5.txt
./prefixes.txt
./foo_2.txt
$ foo=( $(find . -name "*.txt*" | grep -f prefixes.txt) )
$ set | grep ^foo=
foo=([0]="./foo_1.txt" [1]="./bar_3.txt" [2]="./bar_4.txt" [3]="./foo_2.txt")
Note though that this will break on filenames with whitespace and there is probably a better solution to your actual problem.
set -A aRray `find . -name "*" | egrep -f RegExPrefix.txt | sed "s/.*/'&'/"`
will depend on your shell. Here is tested with a ksh on AIX (so not a GNU sed and set -A create an array)

Resources