How to count the occurence of a string in a file, for all files in a directory and output into a new file with shell - grep

I have hundreds of files in a directory that I would like to count the occurrence of a string in each file.
I would like the output to be a summary file that contains the original file name plus the count (ideally on the same line)
for example
file1 6
file2 3
file3 4
etc
Thanks for your consideration

CAUTION: I am pretty much an enthusiastic amateur, so take everything with a grain of salt.
Several questions for you - depending on your answers, the solution below may need some adjustments.
Are all your files in the same directory, or do you also need to look through subdirectories and sub-subdirectories, etc.? Below I make the simplest assumption - that all your files are in a single directory.
Are all your files text files? In the example below, the directory will contain text files, executable files, symbolic links, and directories; the count will only be given for text files. (What linux believe to be text files, anyway.)
There may be files that do not contain the searched-for string at all. Those are not included in the output below. Do you need to show them too, with a count of 0?
I assume by "count occurrences" you mean all of them - even if the string appears more than once on the same line. (Which is why a simple grep -c won't cut it, as that only counts lines that contain the substring, no matter how many times each.)
Do you need to include hidden files (whose name begins with a period)? In my code below I assumed you don't.
Do you care that the count appears first, and then the file name?
OK, so here goes.
[oracle#localhost test]$ ls -al
total 20
drwxr-xr-x. 3 oracle oinstall 81 Apr 3 18:42 .
drwx------. 39 oracle oinstall 4096 Apr 3 18:42 ..
-rw-r--r--. 1 oracle oinstall 40 Apr 3 17:44 aa
lrwxrwxrwx. 1 oracle oinstall 2 Apr 3 18:04 bb -> aa
drwxr-xr-x. 2 oracle oinstall 6 Apr 3 17:40 d1
-rw-r--r--. 1 oracle oinstall 38 Apr 3 17:56 f1
-rw-r--r--. 1 oracle oinstall 0 Apr 3 17:56 f2
-rwxr-xr-x. 1 oracle oinstall 123 Apr 3 18:15 zfgrep
-rw-r--r--. 1 oracle oinstall 15 Apr 3 18:42 .zz
Here's the command to count 'waca' in the text files in this directory (not recursive). I define a variable substr to hold the desired string. (Note that it could also be a regular expression, more generally - but I didn't test that so you will have to, if that's your use case.)
[oracle#localhost test]$ substr=waca
[oracle#localhost test]$ find . -maxdepth 1 -type f \
> -exec grep -osHI "$substr" {} \; | sed "s/^\.\/\(.*\):$substr$/\1/" | uniq -c
8 aa
2 f1
1 .zz
Explanation: I use find to find just the files in the current directory (excluding directories, links, and whatever other trash I may have in the directory). This will include the hidden files, and it will include binary files, not just text. In this example I find in the current directory, but you can use any path instead of . I limit the depth to 1, so the command only applies to files in the current directory - the search is not recursive. Then I pass the results to grep. -o means find all matches (even if multiple matches per line of text) and show each match on a separate line. -s is for silent mode (just in case grep thinks of printing messages), -H is to include file names (even when there is only one file matching the substring), and -I is to ignore binary files.
Then I pass this to sed so that from each row output by grep I keep just the file name, without the leading ./ and without the trailing :waca. This step may not be necessary - if you don't mind the output like this:
8 ./aa:waca
2 ./f1:waca
1 ./.zz:waca
Then I pass the output to uniq -c to get the counts.
You can then redirect the output to a file, if that's what you need. (Left as a trivial exercise - since I forgot that was part of the requirement, sorry.)

Thanks for the detailed answer it provides me with ideas for future projects.
In my case the files were all the same format (output from another script) and the only files in the directory.
I found the answer in another thread
grep -c -R 'xxx'

Related

What does the <nixpkgs> string / value mean in Nix?

For example in the following (which I assume is a nix expression):
(import <nixpkgs> {}).haskellPackages.ghcWithPackages (hpkgs: with hpkgs; [
lens
aeson
turtle
])
What does <nixpkgs> reference? I also see it used in other contexts for example:
nix-shell '<nixpkgs>' -A linuxPackages.kernel
<nixpkgs> is a Nix expression that is evaluated by looking at the Nix search path in the NIX_PATH environment variable and/or -I option.
It is described in more detail in the Nix manual.
Note that the Nix search path is impractical in many situations. You can only pass it from the outside, and it easily creates impurity. In my experience, problems are better solved with explicit argument passing or the functions relating to fix-points like callPackage and the overlay system.
As an example, NixOS has only one extra search path parameter, and it is only read once in nixos/default.nix if no explicit configuration is given. This way, you have the flexibility to provide your own configuration, which is why you (nix-build) and hydra can confidently build the NixOS VM tests, bootable images, docker images, etc.
From the Nix manual, 5.2.1. Values, section "Simple Values":
Paths can also be specified between angle brackets, e.g. .
This means that the directories listed in the environment variable
NIX_PATH will be searched for the given file or directory name.
From the NixOS manual, 7.2. Common Environment Variables, section NIX_PATH:
A colon-separated list of directories used to look up Nix expressions
enclosed in angle brackets (i.e., ). For instance, the value
/home/eelco/Dev:/etc/nixos
will cause Nix to look for paths relative to /home/eelco/Dev and
/etc/nixos, in that order. It is also possible to match paths
against a prefix. For example, the value
nixpkgs=/home/eelco/Dev/nixpkgs-branch:/etc/nixos
will cause Nix to search for <nixpkgs/path> in
/home/eelco/Dev/nixpkgs-branch/path and /etc/nixos/nixpkgs/path.
If a path in the Nix search path starts with http:// or https://,
it is interpreted as the URL of a tarball that will be downloaded and
unpacked to a temporary location. The tarball must consist of a single
top-level directory. For example, setting NIX_PATH to
nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/nixos-15.09.tar.gz
tells Nix to download the latest revision in the Nixpkgs/NixOS 15.09
channel.
A following shorthand can be used to refer to the official channels:
nixpkgs=channel:nixos-15.09
The search path can be extended using the -I option, which takes
precedence over NIX_PATH.
Examples
1. with import <nixpkgs> {}; /* rest of the expression */
In my case, <nixpkgs> is /nix/var/nix/profiles/per-user/root/channels/nixos:
$ echo $NIX_PATH
# VVVVVVV
/home/a_user/.nix-defexpr/channels:nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixos:nixos-config=/etc/nixos/configuration.nix:/nix/var/nix/profiles/per-user/root/channels
# ^^^^^^^
Because <nixpkgs> evaluates to "a directory, the file default.nix in that directory is loaded" by import. (Nix manual, 15.4.1. Advanced Attributes, section import path, builtins.import path)
$ ll /nix/var/nix/profiles/per-user/root/channels/nixos
lrwxrwxrwx 1 root root 80 Dec 31 1969 /nix/var/nix/profiles/per-user/root/channels/nixos -> /nix/store/ywlfq2ns4
a3fzb2ap74lvahmrg1p0lmk-nixos-19.03.172231.7b36963e7a7/nixos/
$ ll $(readlink -f /nix/var/nix/profiles/per-user/root/channels/nixos)
total 3308
dr-xr-xr-x 8 root root 4096 Dec 31 1969 ./
dr-xr-xr-x 4 root root 4096 Dec 31 1969 ../
# (...)
dr-xr-xr-x 7 root root 4096 Dec 31 1969 nixos/
dr-xr-xr-x 17 root root 4096 Dec 31 1969 pkgs/
-r--r--r-- 1 root root 1097 Dec 31 1969 COPYING
-r--r--r-- 1 root root 968 Dec 31 ---> default.nix <---
# (...)
If my understanding is correct, after the import the provided Nix expression is evaluated with an empty attribute set ({}). The result is an attribute list, and the with expression will include all its containing attributes in the local lexical scope.
2. nix repl '<nixpkgs/nixos>'
Example taken from the NixOS manual, 5.3. Modularity, showing the active NixOS configuration settings in the repl.
# On NixOS 19.03
$ nix repl
Welcome to Nix version 2.2.2. Type :? for help.
nix-repl> <nixpkgs>
/nix/var/nix/profiles/per-user/root/channels/nixos
nix-repl> <nixpkgs/nixos>
/nix/var/nix/profiles/per-user/root/channels/nixos/nixos
Load the systems NixOS configuration on the repl:
nix-repl> :l <nixpkgs/nixos>
Added 6 variables.
Load all Nix expressions from Nixpkgs on the repl:
nix-repl> :l <nixpkgs>
Added 10089 variables.
Or loading them directly into the repl:
$ nix repl '<nixpkgs>'
Welcome to Nix version 2.2.2. Type :? for help.
Loading '<nixpkgs>'...
Added 10089 variables.
$ nix repl '<nixpkgs/nixos>'
Welcome to Nix version 2.2.2. Type :? for help.
Loading '<nixpkgs/nixos>'...
Added 6 variables.
Cheatsheet:
nix-repl> :help
The following commands are available:
<expr> Evaluate and print expression
<x> = <expr> Bind expression to variable
:a <expr> Add attributes from resulting set to scope
:b <expr> Build derivation
:i <expr> Build derivation, then install result into current profile
:l <path> Load Nix expression and add it to scope
:p <expr> Evaluate and print expression recursively
:q Exit nix-repl
:r Reload all files
:s <expr> Build dependencies of derivation, then start nix-shell
:t <expr> Describe result of evaluation
:u <expr> Build derivation, then start nix-shell
Because of the <nixpkgs/path> convention (where path equals nixos), the angle expression will evaluate to /nix/var/nix/profiles/per-user/root/channels/nixos/nixos. The above ll output also shows a nixos folder above default.nix, and inside there is indeed another default.nix that will get evaluated by nix repl:
$ ll $(readlink -f /nix/var/nix/profiles/per-user/root/channels/nixos/nixos)
total 72
dr-xr-xr-x 7 root root 4096 Dec 31 1969 ./
dr-xr-xr-x 8 root root 4096 Dec 31 1969 ../
-r--r--r-- 1 root root 886 Dec 31 ---> default.nix <---
-r--r--r-- 1 root root 197 Dec 31 1969 README
-r--r--r-- 1 root root 6074 Dec 31 1969 release-combined.nix
-r--r--r-- 1 root root 9251 Dec 31 1969 release.nix
-r--r--r-- 1 root root 2038 Dec 31 1969 release-small.nix
Miscellaneous
Issue #338 is still open to improve the Nix manual, documenting the angle syntax in their own section (UPDATE: Fixed and closed, 10/23/2019).
Nix Pills sections (e.g., 15.5. Conclusion and Chapter 16. Nixpkgs Parameters) consistently call the angle syntax "angular brackets" syntax.
In his answer, Robert Hensing warns against using <nixpkgs> everywhere, and an issue #1161 is still open on just that topic. (Excerpt: "We have an unofficial guideline that nobody should use angle brackets in nixpkgs, but why not make it into a hard requirement?")
One can evaluate the value using nix repl:
 nix repl
Welcome to Nix version 2.1.3. Type :? for help.
nix-repl> <nixpkgs>
/nix/var/nix/profiles/per-user/root/channels/nixos

How messages from printf are routed to the terminal?

Lets say I have opened two tabs in the konsole (Tab1 and Tab2).
When I run tty in both of them I have:
Tab1:
~$ tty
/dev/pts/23
Tab2:
~$ tty
/dev/pts/24
If I run a simple program hello.c with a printf("Hello") in Tab1, how the system goes from writing to the stdout (file id 1) to writing to /dev/pts/23, being read by the konsole and then appearing in Tab1?
How the system know it has to give the "Hello" string to /dev/pts/23 and not to /dev/pts/24? And how it does that?
Is there a parameter given by the bash to the program so it knows which psudoterminal to send the "Hello"? Or the program sends the string back to the bash (how?) who knows to which pseudoterminal to send the data?
Thank you for your help
If you look at your process open files, you can see that the STDOUT,STDERR, etc points to the specific psuedo terminal that you already figured out using tty in your question
root#hello:~# ls -l /proc/self/fd
total 0
lrwx------ 1 root root 64 May 21 02:18 0 -> /dev/pts/3
lrwx------ 1 root root 64 May 21 02:18 1 -> /dev/pts/3
lrwx------ 1 root root 64 May 21 02:18 2 -> /dev/pts/3
As you might know, a process is created by a fork system call that actually duplicates the open file descriptors from the parent. so basically, your process gets the file descriptors from its parent.
How did the parent hot these associated with him ? well, konsole already dealt with that.

Interesting issues related to how 'cp --parents' works

I've written a short csh script that reads a file, which contains paths to files to be copied, then copies those files to a directory:
1 #!/bin/csh
2 #
3 # This script copies source and executable files modified to solve issues
4 # brought up by Veracode.
5 #
6
7 set tempdir = '~/updatedfiles2'
8
9 foreach line ( "`cat modifiedFiles`" )
*************here is the cp line**************
10 `cp -a $line $tempdir`
**********************************************
11 end
Which previously worked fine. I've since decided that I want to preserve the paths to these files in the form of a directory tree under that same tempdir directory because colisions are occuring when files with different paths have the same names.
(i.e. /vobs/emv/integratedClient/jniWrapper/OEMIMAKEFILE and /vobs/mv_components/utilities/general/OEMIMAKEFILE)
So, I tried to use the --parents option, like so:
1 #!/bin/csh
2 #
3 # This script copies source and executable files modified to solve issues
4 # brought up by Veracode.
5 #
6
7 set tempdir = '~/updatedfiles2'
8
9 foreach line ( "`cat modifiedFiles`" )
*************here is the cp line**************
10 `cp -a --parents $line $tempdir`
**********************************************
11 end
When I test it, it starts trying to copy the entirety of my system, starting in the root directory, which is not the effect I want. I'm just trying to copy over specific files, maintaining their directory structure as they are copied.
I've found some explanations of --parents, but none describe anything like what I'm seeing happening. Is it because I'm using --parents wrong? Is it my input file? I'm not sure.
The content of modifiedFiles (which is the value of tempdir) looks like this:
...
4 /vobs/emv/C_API/APIPrivate.cpp
5 /vobs/mv_components/utilities/class/Array.c
6 /vobs/mv_components/utilities/class/String1.c
7 /vobs/mv_components/export_functions/code/write_nastran_ortho3_none.c
...
/vobs is a root directory, so this may be effecting something with --parents. Has anyone heard of unrestricted recursive copying, despite specific file paths and no -r argument? Am I misunderstanding --parents?
Wow, I feel dumb.
After looking through it again and again, I've come to find what I've done wrong.
The actual command above is in a csh script. When a command is enclosed in front ticks (``) in a csh script, that command is executed, and the out put of that command is used by the shell. I was therefore doing the cp, then executing the output in the shell. I'm not sure why it was recursively copying upward, but removing those front ticks fixed everything. There was a previous error that I ignored in my original "working" script, and when I added the --parents option, the already broken script broke even more.
Moral of the story, be careful of front ticks!
For anyone who is interested, before:
...
9 foreach line ( "`cat modifiedFiles`" )
*************here is the cp line**************
10 `cp -a --parents $line $tempdir`
**********************************************
11 end
...
And after:
...
9 foreach line ( "`cat modifiedFiles`" )
*************here is the cp line**************
10 cp -a --parents $line $tempdir
**********************************************
11 end
...
Also, two of the entries in the input file were commented out in C style
/* comment */
That was causing the recursive copying from the root directory. Haha....eh. Stupid me.

vim nerdtree files show up with * appended [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
gVim displays every file with an asterisk on the right (and bold)?
I'm using vim with nerdtree plugin for my rails projects and some of the files show up with a * appended to the filename. They are also a different color from the other files.
edit.html.erb*
index.html.erb
show.html.erb*
What does the * mean?
The key is the executable bit. For example, if you do this:
$touch no_exec_file exec_file
$chmod -v u+x exec_file
$ls -lF
total 0
-rwxr--r-- 1 reoo reoo 0 2012-09-19 19:14 exec_file*
-rw-r--r-- 1 reoo reoo 0 2012-09-19 19:14 no_exec_file
You can see the '*' in the exec_file, now, if you open VIM, you can see the '*' symbol again in the exec_file.
So, the NERDTree plugin shows the '*' symbol for those files that can be execute by the user.
It means that your files are executable, meaning you gave them the permission to be executable. Or they are files like .exe for example.

Lua change current/working dir, Linux (without LFS or any non-std modules)

I need to change current working dir in lua script for execute specific actions, but i have a trouble with this simple task.
I write test script test.lua :
os.execute("cd /usr")
os.execute("ls")
But lua test.lua output is:
test.lua
Current dir doesn't change. What's is wrong? And i can't use LFS or any non-std modules.
Thanks to all for explaining it situation. I choose another way : change work dir before run lua script, but i have a lot of troubles with paths which use in scripts and with scripts.
On Unix, os.execute() spawns a child process and its children. In
jpjacobs's answer, the first process would execute the shell.
The directory change operation only affects the child process, not the
process in which the Lua interpreter is executing your program.
It's simply not possible without external libraries. You can use stuff like
os.execute("cd /usr/ && ls")
The Lua standard library is intended to be both small and portable. Therefore, it is based on the capabilities of the C-standard library for all but a select few functions. It has no function to change directories; that's why libraries like LFS exist.
Have you considered that Lua may not be the appropriate language for your needs? If you're doing shell-style scripting work in an environment where you're not allowed to load non-standard modules, perhaps Python or Perl would be better for you. Both of them have extensive standard libraries with a host of features, all without the need to download non-standard modules.
If you want to do any real shell-style scripting in Lua, you need modules. It's that simple. So you should either use external modules or use a different language.
This is a bit of hack, but have you tried creating symbolic links to the folders you need in the current folder, so you don't have to change the current folder at all?
os.execute("ln -s /usr/foo") -- link called "foo" in current dir
os.execute("ln -s /usr/bar") -- link called "bar" in current dir
baz = require('foo.baz') -- loading file /usr/foo/baz.lua
Here is the program written using Zerobranie Lua 5.2:
local sP = "E:/Documents/Lua-Projs/SVN/ScriptsWireE2"
local a, b, c = os.execute("cd "..sP.."&& dir")
print(a,b,c)
And the outpuit:
Програма 'lua.exe' пусната в 'E:\Documents\Lua-Projs\ZeroBraineIDE\ZeroBraineProjects' (pid: 8832).
Volume in drive E is Data
Volume Serial Number is DE34-ED00
Directory of E:\Documents\Lua-Projs\SVN\ScriptsWireE2
08-03-2016 18:25 <DIR> .
08-03-2016 18:25 <DIR> ..
17-03-2016 18:15 <DIR> Bridges
07-03-2016 18:21 11 558 license
07-03-2016 18:21 87 readme.md
2 File(s) 11 645 bytes
3 Dir(s) 181 729 161 216 bytes free
true exit 0
Програмата завършена за 0.06 секунди (pid: 8832).

Resources