Move output of Find command unix - shell

Im learning unix programming , i want to find all files whose size is greater than 1M an print them into a file.
here is my code
find. -size +1M -print0 | xargs -I -O '{}' mv '{}' files
all sites i have found refer to this one as right one , but it does not work . currently im working on ubuntu

You mis-copied/mis-typed the commend from wherever you found it.
The first {} is the argument to -I.
-O is not an argument to xargs you meant -0 (to go with -print0).
You missed the space between find and . (the current directory).
Which would get you:
find . -size +1M -print0 | xargs -0 -I '{}' mv '{}' files
That being said you don't need xargs here at all since find can execute commands directly.
find . -size +1M -exec mv {} files \+
And it is generally a good idea to test a complicated find command before you run it.
Using find . -size +1M by itself will just print the matching files.
Using
find . -size +1M -ok mv {} files \+
will cause find to prompt you before each execution of the command.

Related

Wildcard within if conditional of Bash fails to execute. Works when literal filename provided

I am trying to execute a command depending on the file type within directory. But am unable to check the content within directory using wildcard. When provided a literal filename I am able to execute.
find ./* -type d -execdir bash -c 'DIR=$(basename {}); if [[ -e {}/*.png ]]; then echo "img2pdf {}/*.png -o $DIR.pdf"; fi ' \;
Instead of going over directories, and then looking for png-s inside, find can find png-s straight away:
find . -name '*.png'
Then you can process it as you do, or using xargs:
find . -name '*.png' | xargs -I '{}' img2pdf '{}' -o '{}.pdf'
The command above will process convert each png to a separate pdf.
If you want to pass all png-s at once, and call img2pdf once:
find . -name '*.png' | xargs img2pdf -o out.pdf

What does {} mean in "xargs -I {} unrar x {}"?

I am new to shell and I'd like to learn, however, it seems a bit too complex to understand:
find . \( -name *.rar \) | xargs -I {} unrar x {}
Can you please explain step by step what is does. I know that it goes into folders and finds all the .rar files that it finds and then it chains the files that it finds into the second part of the command using | symbol.
However, I do not understand the xargs -I {} unrar x {} part, and {} command in particular. I know that unrar extracts the archive.
The {} is a placeholder, replaced with a filename in the generated command.
However, don't use this code; it will behave badly with rar archives having unusual names, or if there are any files matching *.rar in the current directory (as opposed to subdirectories). Consider instead:
find . -name '*.rar' -exec unrar x '{}' ';'
...or, if you really want to use xargs:
find . -name '*.rar' -print0 | xargs -n 1 -0 unrar x

using the `find` command with -exec for a lot of files, how can I compare the output against a value?

I am trying to iterate over a large number of images and check their 'mean' value using ImageMagick.
The following command finds the images I want to check, and executes the correct command on them.
find `pwd` -type f -name "*.png" -exec /usr/bin/identify -ping -format "%[mean]" info: {} \;
Now I want to compare the output to see if it comes up with a certain value, 942.333
How can I get the output of each value that find returns to check and spit out the filename of any matched image who has the ouput of 942.333 from my command?
Thanks!
Change your identify command so it outputs the filename and the mean, then use grep:
find `pwd` -type f -name "*.png" -exec identify -ping -format "%[mean] %f\n" {} \; | grep "942.333"
Or, if you really have lots of images, you could put all your lovely CPU cores to work and do them in parallel, using GNU Parallel:
find . -name \*.png -print0 | parallel -m -0 'identify -ping -format "%[mean] %f\n" {1}' | grep ...

Move files of specific size in Ubuntu using Terminal

I want to move all the files in a specific folder having size of 0 bytes. I know that the following prints all the files with size zero bytes.
find /home/Desktop/ -size 0
But i want to move them to another folder, so i tried :
find /home/Desktop/ -size 0 | xargs -0 mv /home/Desktop/a
But that doesn't work. ? Is there any other way to do it.? What am i doing wrong?
You can do that in find itself using -exec option:
find /home/Desktop/ -size 0 -exec mv '{}' /home/Desktop/a \;
find default prints the file name on the standard output followed by a newline. The option -print0 prints the file name followed by a null character instead. The option -0 of xargs means that the input is terminated by a null character.
find /home/Desktop/ -size 0 -print0 | xargs -0 -I {} mv {} /home/Desktop/a
You could instead use find's option -exec
In both cases consider also using find's option -type f if you only want to find files and the option -maxdepth 1 if you do not want find to descend directories. This is specially usefull in your example since you move the found files to a subdirectory!

Number of lines from XCode project [duplicate]

Is there a way to determine how many lines of code an Xcode project contains? I promise not to use such information for managerial measurement or employee benchmarking purposes. ;)
I see this floating around and use it myself:
find . "(" -name "*.m" -or -name "*.mm" -or -name "*.cpp" -or -name "*.swift" ")" -print0 | xargs -0 wc -l
Check out CLOC.
cloc counts blank lines, comment lines, and physical lines of source code in many programming languages.
(Legacy builds are archived on SourceForge.)
I have been using CLOC as mentioned by Nathan Kinsinger and it is fairly easy to use. It is a PERL script that you can add and run from your project directory.
PERL is already part of Mac OS and you can invoke the script this way to find out your number of lines you have written:
perl cloc-1.56.pl ./YourDirectoryWhereYourSourcesAre
This is an example of output i got from such command:
176 text files.
176 unique files.
4 files ignored.
http://cloc.sourceforge.net v 1.56 T=2.0 s (86.0 files/s, 10838.0 lines/s)
-------------------------------------------------------------------------------
Language files blank comment code
-------------------------------------------------------------------------------
Objective C 80 3848 1876 11844
C/C++ Header 92 980 1716 1412
-------------------------------------------------------------------------------
SUM: 172 4828 3592 13256
-------------------------------------------------------------------------------
Open up Terminal.app, go into your project's root directory, and run this command:
For Swift only:
find . \( -iname \*.swift \) -exec wc -l '{}' \+
For Obj-C only:
find . \( -iname \*.m -o -iname \*.mm -o -iname \*.h \) -exec wc -l '{}' \+
For Obj-C + Swift:
find . \( -iname \*.m -o -iname \*.mm -o -iname \*.h -o -iname \*.swift \) -exec wc -l '{}' \+
For Obj-C + Swift + C + C++:
find . \( -iname \*.m -o -iname \*.mm -o -iname \*.c -o -iname \*.cc -o -iname \*.h -o -iname \*.hh -o -iname \*.hpp -o -iname \*.cpp -o -iname \*.swift \) -exec wc -l '{}' \+
Terminal quick tips:
ls: list directory contents
cd: change directory
Press tab to autocomplete
Remember to put "\" backslash before spaces
I suggest going one folder down from the main project so you get rid of code count from the frameworks
In terminal, change into the project directory and run:
find . -type f -print0 | xargs -0 cat | wc -l
If you want only certain file types, try something like
find . -type f -name \*.[ch]* -print0 | xargs -0 cat | wc -l
open terminal
navigate to your project
execute following command inside your project:
find . -path ./Pods -prune -o -name "*.swift" -print0 ! -name "/Pods" | xargs -0 wc -l
Or:
find . -path ./Pods -prune -o -name "*[hm]" -print0 ! -name "/Pods" | xargs -0 wc -l
(*Excluding pod files count from total count)
Check out Xcode Statistician, it does exactly what you want. It also provides other interesting statistics so is worth a run for fun now and then.
Note that it will not look inside real folders, though it will look in groups. Odds are you aren't using real folders so it'll work great. If you are using folders then you just have to do the count in each folder and add them together.
Note: As of June, 2012, it seems this does not work properly with the latest versions of Xcode.
If you go to your project's directory in terminal and enter:
find . "(" -name "*.h" -or -name "*.m" -or -name "*.mm" -or -name "*.hpp" -or -name "*.cpp" -or -name "*.c" -or -name "*.cc" -or -name "*.swift" ")" -print0 | xargs -0 wc -l
That will give you a project breakdown, as well as the line total for each file and the project as a whole.
Steps to implement CLOC library in Mac as below:
Open Terminal.
Install Homebrew by copying and pasting the below command in the Terminal (including double quotes).
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
Enter system password if asked.
You will see the terminal screen as below.
System will popup so many permissions, allow all the permissions
If everything goes fine, you will see terminal screen as below,
Now its time to install CLOC using below command.
brew install cloc
Navigate to the project directory and run either of the following commands.
cloc . --exclude-dir=Pods (to exclude pod files)
cloc . (including pod files)
If everything goes fine, it will display the number of lines of code as below,
Nozzi's version doesn't work for me, but this one:
find . -type f -print0 | xargs -0 cat | wc -l
A quick & easy way:
Use a regex search (Find Navigator, choose Find > Regular Expression).
.\n
Works conveniently with Xcode search scopes and you can easily customize it to whatever type of line you'd like to count ;).
You can install SLOCCount through MacPorts. Or, more crudely, you can use wc -l.
I am not familiar with xcode, but if all you need is to count the number of lines from all those specific files within a directory tree, you may use the following command:
find .... match of all those files ... -exec wc -l {} +
Following Joshua Nozzi's answer, in GNU find the regular expression for such files would be like:
find . "(" -name "*.m" -or -name "*.mm" -or -name "*.cpp" -or -name "*.swift" ")" -exec wc -l {} +
or even
find -regex ".*\.\(m\|mm\|cpp\|swift\)$" -exec wc -l {} +
this uses a regular expression to match all files ending in either .m, .mm, .cpp or .swift. You can see more information about those expressions in How to use regex in file find.
If you are working with Mac OS find, then you need a slightly different approach, as explained by Motti Shneor in comments:
find -E . -regex ".*\.([hmc]|mm|cp+|swift|pch)$" -exec wc -l {} +
Both will provide an output on the form of:
234 ./file1
456 ./file2
690 total
So you can either keep it like this or just pipe to tail -1 (that is, find ... | tail -1) so that you just get the last line being the total.
line-counter is a good alternative. It's lighter than CLOC and much more powerful and easier to use than other commands.
A quick overview
This is how you get the tool
$ pip install line-counter
Use line command to get the file count and line count under current directory (recursively)
$ line
Search in /Users/Morgan/Documents/Example/
file count: 4
line count: 839
If you want more detail, just use line -d.
$ line -d
Search in /Users/Morgan/Documents/Example/
Dir A/file C.c 72
Dir A/file D.py 268
file A.py 467
file B.c 32
file count: 4
line count: 839
And the best part of this tool is, you can add .gitignore like configure file to it. You can set up rules to select or ignore what kind of files to count just like what you do in '.gitignore'. Yes, this tool is just invented to make knowing how many lines I have easier.
More description and usage is here: https://github.com/MorganZhang100/line-counter
I'm the author of this simple tool. Hope it can help somebody.

Resources