finding multiple lines patterns and stop after first occurence - linux

I have got plenty of files in different location including */synth/debug/* in their path pattern, all files have got *.list extension. Files look like:
MODULE XYZ
SIGNED_A 0
WIDTH 12
SIGNED_B 1
(...)
MODULE XXX
SIGNED_A 1
WIDTH 12
SIGNED_B 0
(...and so on...)
I need to find first file with MODULE XXX (the same for XYZ and so on) and SIGNED*1 pattern in the first 3 line after MODULE XXX and stop searching. SIGNED word appears always in 1-3 line after MODULE.
I've got something like that:
find . -name *.list -path "*/synth/debug/*" -type f -exec grep -FHI "MODULE XXX" -A 3 {} \; | grep "SIGNED 1" -A 3 | head -1
but got:
find: ‘grep’ terminated by signal 13
after first (correct) occurence and the command still searching and parsing files wasting the time.

Using awk
find . -name *.list -path "*/synth/debug/*" -type f -exec awk '/MODULE XXX/{xxx=1;next}xxx{xxx+=1}/SIGNED.*1/&&xxx<=4{print FILENAME; exit}xxx>4{nextfile;}ENDFILE{xxx=0}' {} +
Output is name of the first file matching your conditions
Remove xxx>4{nextfile;} if a file contains multiple MODULE XXX blocks
To process every module in 1 command :
find . -name *.list -path "*/synth/debug/*" -type f -exec awk '/MODULE/{current=$2; line=1; next}current in results{next;}{line+=1}/SIGNED.*1/&&line<=4{results[current]=FILENAME}END{for(module in results){print module, results[module]}}' {} +
Output : module name + first file matching conditions :
ABC file2.txt
XXX file1.txt
XYZ file1.txt

Related

How to count files in specific subdirectories of a parent directory?

I use the find . -type f | wc -l command to count all the files in a regular directory, but in more specific cases if a directory contains many files, is it possible to specify this in the command? In case I only want to count all the files in the image subdirectories for example. To know how many images (all in .jpeg) I have in total in mydirectory.
This command works find /Users/mydirectory -type f -exec file --mime-type {} \; | awk '{if ($NF == "image/jpeg") print $0 }' but just display them. How to count them?
Finally the command find /Users/mydirectory -type f -exec file --no-pad --mime-type {} + | awk '$NF == "image/jpeg" {$NF=""; sub(": $", ""); print}' | wc -l seems to do the trick.
mydirectory/
folder1/
image/
label/
folder2/
image/
label/
...
I have the impression that you are not aware of the maxdepth parameter of the find command, which indicates the depth of your search command: by using find ... -maxdepth 1 you say that you only want to search within the directory itself. I believe this will solve your question.
Simple example: I created a subdirectory "tralala" and added two files, a subsubdirectory with one file, and I launched following command:
find tralala -maxdepth 1 -type f | wc -l
The answer was 2, which was correct, as you can see here from the amount "to be counted":
Prompt$ find tralala -ls
... drwxrwxrwx ... tralala/ => is a directory, don't count.
... drwxrwxrwx ... tralala/dir => is a directory, don't count.
... -rwxrwxrwx ... tralala/dir/test.txt => is inside subdirectory, don't count.
... -rwxrwxrwx ... tralala/test.txt => is file inside directory, to be counted.
... -rwxrwxrwx ... tralala/test2.txt => is file inside directory, to be counted.

Constructing a UNIX pipeline that finds all files in a directory (using find ,xargs and du commands )

I need to construct a UNIX pipeline that finds all files under the directory containing the word "english" (using find command)and calculate the size of each and sort them .
This is my implementation and I am getting an assertion error, any inputs will be appreciated
find /usr/share/dict -type f -name "english*"| xargs -n 1 du | sort -n
The error message is
E AssertionError: assert 44 == 2
E + where 44 = len(['4\t./.git/branches\r', '4\t./.git/objects/info\r', '4\t./.git/objects/pack\r', '4\t./.git/refs/tags\r', '8\t./.cache/v/cache\r', '8\t./.git/info\r', ...])
Two error:
Files can contain "spaces" - user print0
It's must be files. Use -type f
find /usr/share/dict -type f -name "english*" -print0| xargs -0 du | sort -n

How can I output the result of find and grep as filename => found

How can I combine the result of commands find and grep in the format: filename: => string?
For example, find . -maxdepth 2 -type f -name .env -exec grep 'CURRENT_ENV' {} \; The command will display me the line when CURRENT_ENVstring found, e.g. CURRENT_ENV=staging. I want to modify the output in the follow way: ./site1.com: CURRENT_ENV=staging.
I can't understand How can I reach that. Is it possible?
-H, --with-filename
Print the file name for each match. This is the default when
there is more than one file to search.
http://man7.org/linux/man-pages/man1/grep.1.html

How to find a name containing "space" in a file?

I have a BD.txt file with the following content:
Person1:Boston:20
Person2:New York:18
Person3:New York:25
Person4:New Orleans:30
I have to show how many people live in New York. I used:
cat BD.txt | grep New York | wc -l
The output was "3" instead of 2. "New York" has a space char on its name, and it finds only "new" (counting some results I don't want, like "New Orleans").
What should I use to find words containing sapce?
Use quotation marks around New York:
cat BD.txt | grep "New York" | wc -l
if I read the question correctly then it states to find the files having space in their name so below command will work
to find files in current directory only
find . -maxdepth 1 -type f -name \*' '\* -prune
to find files in all subdirectories also
find . -type f -name \*' '\*

How to find files on Linux with a name shorter than n characters?

How can I find files on Linux that have a filename shorter than n characters?
For example, to have something to work with, I am looking recursively for all filenames within /home/myuser that are less than 5 characters long (so, a file with name foo should be found, but with name barbaz not because its name is longer than 4 characters) - how can I do so?
The -name option of find operates on the file name without the path. You can't say "shorter than" in a pattern, but you can say "longer than" and negate:
find . -not -name '?????*'
Please try out this
find . -type f -exec basename {} \; | awk '{ if(length($0) < n) print $0 }'
where 'n' is no. of characters

Resources