Script using find to count lines of code - bash

I'm trying to create a shell script that will count the number of lines of code in one folder.
I got this:
h=find . -type f -name \*.[h]* -print0 | xargs -0 cat | wc -l
m=find . -type f -name \*.[m]* -print0 | xargs -0 cat | wc -l
expr $m + $h
But when I'm trying to run it I get this:
lines-of-code: line 6: .: -t: invalid option
.: usage: . filename [arguments]
0
lines-of-code: line 7: .: -t: invalid option
.: usage: . filename [arguments]
0
+
I know I have to do something to make it run on the specific folder I'm in. Is this even possible?

DDIYS (don't to it your self) Use cloc instead. Excelent tool written in perl that does the counting for you as well as a other things. It recognizes more than 80 languages.
Example output:
prompt> cloc perl-5.10.0.tar.gz
4076 text files.
3883 unique files.
1521 files ignored.
http://cloc.sourceforge.net v 1.50 T=12.0 s (209.2 files/s, 70472.1 lines/s)
-------------------------------------------------------------------------------
Language files blank comment code
-------------------------------------------------------------------------------
Perl 2052 110356 130018 292281
C 135 18718 22862 140483
C/C++ Header 147 7650 12093 44042
Bourne Shell 116 3402 5789 36882
Lisp 1 684 2242 7515
make 7 498 473 2044
C++ 10 312 277 2000
XML 26 231 0 1972
yacc 2 128 97 1549
YAML 2 2 0 489
DOS Batch 11 85 50 322
HTML 1 19 2 98
-------------------------------------------------------------------------------
SUM: 2510 142085 173903 529677
-------------------------------------------------------------------------------

Quote the commands like:
h=$(find . -type f -name *.[h]* -print0 | xargs -0 cat | wc -l)
Please also have a look at sloccount for counting lines of code. You can install it on debian/ubuntu with sudo apt-get install sloccount

For this specific problem, I have a different solution:
find . -type f -print0 | wc --files0-from=-

May be I misunderstood the question, but does this work for you?
wc -l *.[mh]*

Now it works!
h=$(find . -type f -name \*.[h]* -print0 | xargs -0 cat | wc -l)
m=$(find . -type f -name \*.[m]* -print0 | xargs -0 cat | wc -l)
expr $m + $h

Related

How to check if a folder has any tab delimited file in it?

I am trying to search for all the tab delimited file in one folder, and if found any then I need to transfer all of them to a another folder using bash.
In my code, I am currently trying to find all files, but somehow it is not working.
Here is my code:
>nul 2>nul dir /a-d "folderName\*" && (echo Files exist) || (echo No file found)
Thanks in advance :)
For a simple move (or copy -- replace mv with cp) of files, #tripleee's answer is sufficient. To recursively search for files and run a command on each, find comes in handy.
Example:
find <src> -type f -name '*.tsv' -exec cp {} <dst> \;
Where <src> is the directory to copy from, and <dst> is the directory to copy to. Note that this searches recursively, so any files with duplicate names will cause overwrites. You can pass -i to cp to have it prompt before overwriting:
find <src> -type f -name '*.tsv' -exec cp -i {} <dst> \;
Explained:
find <src> -type f -name '*.tsv' -exec cp -i {} <dst> \;
^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^^
| | | | | | | | | | | ||
| | | | | | | | | | | | --- terminator
| | | | | | | | | | | --- escape for terminator
| | | | | | | | | | --- destination directory
| | | | | | | | | --- the path of each file found
| | | | | | | | --- prompt before overwriting
| | | | | | | --- the copy command
| | | | | | --- flag for executing a command (cp in this case)
| | | | | --- pattern of files to match
| | | | --- flag for specifying file name pattern
| | | --- 'f' for a regular file (as opposed to e.g. 'd' for directory)
| | --- flag for specifying the file type
| --- location to search
--- the find command, useful for searching for files
To get a feel for what happens without actually having find run the real command, you can prefix it with echo to just print each command instead of running it:
find <src> -type f -name '*.tsv' -exec echo cp -i {} <dst> \;
Your attempt has very little valid Bash script in it.
mv foldername/*.tsv otherfolder/
There will be an error message if there are no matching files.
"it is not working". That means very little on stackoverflow.
Let's first examine what you've done:
>nul 2>nul dir /a-d "folderName\*"
So, you're doing a dir (most Linux users would use ls, but soit) on
/a-d
everything under folderName
and the output is in the file nul. For debugging purposes, it would be good to see what is in nul (do cat nul). I would bet it is something like:
dir: cannot access '/a-d': No such file or directory
dir: cannot access 'folderName\*': No such file or directory
That means that dir exits with an error. So, echo No file found will be executed.
This means that your output is probably
No file found
Which is exactly as expected.
In your code, you said you want to find all files. That means you want the output of
ls folderName
or
find folderName
if you want to do things recursively. Because find has been explained above by jsageryd, I won't elaborate on that.
If you just want to look in that specific directory, you might do:
if dir folderName/*.tsv > nul 2>nul ; then
echo "Files exist"
else
echo "No file found"
fi
and go from there.

error in script containing grep

I am getting GREP invalid option error in the code below :
file=$(find . -mtime -4 |ls -lt)
for f in $file
do
po=$(echo $f|cut -d"_" -f2)
find . -mtime -4 |ls -lt|grep "$po"|while read fn
do
if [ -s $fn ]; then #checks if the file is not empty
if [ -d tmp ]; then
rm -r tmp
fi
mkdir tmp
cp -p $fn /tmp/$fn
break
fi
done
done
Basically I am trying to sort the list which I am getting from find then looping through it taking the latest non zero file for a PO.
List of file is
-rw-rw-r-- 1 loneranger loneranger 37 Jul 21 06:30 belk_po12345_20140721.log
-rw-rw-r-- 1 loneranger loneranger 24 Jul 22 06:30 belk_po12345_20140722.log
-rw-rw-r-- 1 loneranger loneranger 0 Jul 23 06:30 belk_po12345_20140723.log
-rw-rw-r-- 1 loneranger loneranger 11 Jul 24 12:00 belk_po12348_20140723.log
PO - po12345 or po12348 these are...
Basically I am trying to sort the list which I am getting from find
then looping through it taking the latest non zero file for a PO.
You might use find for all of that except the final sort:
find . -size '+1c' -type f -printf "%f %T#\n" | sort -k2
The find part search files (-type f) of more than 1 byte long (-size '+1c') and for each one print the file's base name (%f) and the modified time as seconds since Jan. 1, 1970, 00:00 GMT (%T#). After that, it is a simple sort on the second field (timestamp).
Of course, you might add all the search criterion you need on find but that's the basic idea.
And if you want to loop over the result, do as usual:
find . -size '+1c' -type f -printf "%f %T#\n" |
sort -k2 |
while read fname mts; do
# ...
done

Finding which files are taking up most space

On a mac terminal, I want to find out which files are the biggest in my project.
I try:
du -h | sort
But this sorts by path first and then within path the file size. How do I do it just for file size?
Thanks
Try
du -scm * | sort -n
If you want to have it as a nice zsh function you can use this:
function dudir () { du -scm ${1:-*(ND)} | sort -n }
Sort by numeric/reversed:
$ du -sk * | sort -nr
190560 find_buggy_pos.out
126676 DerivedData
29460 fens.txt
11108 cocos2d_html.tar.gz
484 ccore.log
164 ccore.out
16 a.out.dSYM
12 x
12 p
12 o
12 a.out
4 x.txt
4 trash.c
4 test2.cpp
4 test.cpp
4 stringify.py
4 ptest.c
4 o.cpp
4 mismatch.txt
4 games.pgn
It appears that you want to list files by size. Try:
find . -type f -printf "%s %p\n" | sort -n
(By default, du doesn't list counts for files. Use the -a or --all option to list count for files as well.)
On OSX following works:
find . -maxdepth 1 -type f -exec du -k {} \; | sort -nr
Use -k option:
du -sk * | sort -n

Folders tree with rights

In OS X and SunOS OS there is no exist the 'bash tree command'.
To plot a tree "graph" of folders i use the following instruction:
find . -type d -print | sed -e 's;[^/]*/;|____;g;s;____|; |;g'
Or this to show files too.
find . -print | sed -e 's;[^/]*/;|____;g;s;____|; |;g'
But i need another version which contains also the folders rights. Im pretty lost to add on the right side the folder rights. Anyone have any idea ??
Update:
There are any option to plot the files inside the folders and their rights too. I'm trying with this command find . -print | sed -e 's;[^/]*/;|____;g;s;____|; |;g' and doing combination with the solution provided by #fedorqui but the result aren't so good.
That's the result obtained with the above command, without rights.
| | |____src
| | | |____cft2exit.c
| | | |____cft2exit_AIX
| | | |____cft2exit_SUN
| | | |____gestidt.c
| | | |____gestidt.h
| | | |____gestidt.o
| | | |____gestidt_AIX
| | | |____gestidt_SUN
| | | |____gestidt_SunOS
| | | |____makefile
| | | |____sem.a
| | | |____ut_sem.c
| | | |____ut_sem.h
| | | |____ut_sem.o
| |____data
| | |____purge.dat
| |____lost+found
You can execute ls -ld for each result of find. It will give you the permissions, other things, and then the file name. If you then pipe to awk, with awk '{print $NF, $1}' you can print both blocks of information. Finally, you pipe to your sed command. All together:
find . -type d -exec ls -ld {} \; | awk '{print $NF, $1}' | sed -e 's;[^/]*/;|____;g;s;____|; |;g'
Test
$ find . -type d -exec ls -ld {} \; | awk '{print $NF, $1}' | sed -e 's;[^/]*/;|____;g;s;____|; |;g'
. drwxrwxr-x
|____python drwxrwxr-x
| |____jinja2 drwxrwxr-x
| | |____bk drwxrwxr-x
| | |____infiles drwxrwxr-x
.......
In small steps:
$ find . -type d -exec ls -ld {} \;
drwxrwxr-x 7 me me 4096 Aug 15 15:35 .
drwxrwxr-x 3 me me 4096 Aug 13 14:31 ./python
drwxrwxr-x 4 me me 4096 Apr 26 15:14 ./python/jinja2
drwxrwxr-x 2 me me 4096 Apr 19 14:26 ./python/jinja2/bk
drwxrwxr-x 2 me me 4096 Apr 19 12:54 ./python/jinja2/infiles
and then
$ find . -type d -exec ls -ld {} \; | awk '{print $NF, $1}'
. drwxrwxr-x
./python drwxrwxr-x
./python/jinja2 drwxrwxr-x
./python/jinja2/bk drwxrwxr-x
./python/jinja2/infiles drwxrwxr-x
On OS X you can install tree, using homebrew:
brew install tree
or, using macports:
sudo port install tree
and then, to view directories with permissions:
$ tree -p -d
Sample output:
.
├── [drwxr-xr-x] folder1
│   └── [drwxr-xr-x] folder2
│   └── [drwxr-xr-x] folder3
│   └── [drwxr-xr-x] folder4
└── [drwxr-xr-x] folder5
├── [drwxr-xr-x] folder6
└── [drwxr-xr-x] folder7

Bash: Limit output of ls and grep

Let me present an example and than try to explain my problem:
noob#noob:~/Downloads$ ls | grep srt$
Elementary - 01x01 - Pilot.LOL.English.HI.C.orig.Addic7ed.com.srt
Haven - 01x01 - Welcome to Haven.DVDRip.SAiNTS.English.updated.Addic7ed.com.srt
Haven - 01x01 - Welcome to Haven.FQM.English.HI.C.updated.Addic7ed.com.srt
Supernatural - 08x01 - We Need to Talk About Kevin.LOL.English.HI.C.updated.Addic7ed.com.srt
The Big Bang Theory - 06x02 - The Decoupling Fluctuation.LOL.English.HI.C.orig.Addic7ed.com.srt
Torchwood - 1x01 - Everything changes.0TV.English.orig.Addic7ed.com.srt
Torchwood - 1x01 - Everything changes.divx.English.updated.Addic7ed.com.srt
Now I only want to delete the first four results of the above command. Normally if I have to delete all the files I would do ls | grep srt$ | xargs -I {} rm {} but in this case I only want to delete the top four.
So, how can limit the output of ls and grep or suggest me an alternate way to achieve this.
You can pipe your commands to head -n to limit to n lines:
ls | grep srt | head -4
$ for i in `seq 1 345`; do echo $i ;done | sed -n '1,4p'
1
2
3
4
geee: ~
$ for i in `seq 1 345`; do echo $i ;done | sed -n '335,360p'
335
336
337
338
339
340
341
342
343
344
345
If you don't have too many files, you can use a bash array:
matching_files=( *.srt )
rm "${matching_files[#]:0:4}"

Resources