Find command in linux - linux

What does the following means ?
find myDirectory -name myFile -exec ls \-ln {} \;
I've looked here but didn't understand exactly
-exec command True if the executed command returns a zero value as exit status. The end of command must be punctuated by an escaped semicolon. A command argument {} is replaced by the current path name.
This part -exec ls \-ln {} \; is not clear to me .
Regards

That means: find all files with a name myFile in the current directory and all its subdirectories and for every file that was found run ls -ln with the name of the file.
For example:
$ mkdir a
$ touch myFile a/myFile
$ find -name myFile -exec ls -ln {} \;
-rw-r--r-- 1 1000 1000 0 Jun 17 13:07 ./myFile
-rw-r--r-- 1 1000 1000 0 Jun 17 13:07 ./a/myFile
In this case find will run ls twice:
ls -ln ./myFile
ls -ln ./a/myFile
Every time it will expand {} as the fullname of the found file.
Also I must add that you need the backslash before -ln in this case. Yes, you can use it, but it is absolutely useless here.

find myDirectory -name myFile -exec ls \-ln {} \;
It says find myFile in directory myDirectory and once all the files are found then execute the file listing command, that is in linix ls with command options -l and -n on the files found.
So, ultimately you will get all the myFiles accompanied with ls command result.

Related

printing directory with simple ls and grep command Linux

So I have this command ls -al -R | grep libbpf.h and it just act dump print
-rw-r--r-- 1 root root 53107 جنوری 27 12:05 libbpf.h
I also need the exact subdirectories that contain this file is there a way I can use the above command with some option for grep or ls so it also prints some thining like
-rw-r--r-- 1 root root ./libbpf/src/include/libbpf.h 53107 جنوری 27 12:05 libbpf.h
so I only knows the the libbpf.h does exists in somewhere from root directory recursively searching just give me the path, does any one knows this
you can use find command
find "$(pwd -P)" -type f -name "libbpf.h" -ls
if you want only paths
find "$(pwd -P)" -type f -name "libbpf.h"
or
find . -type f -name "libbpf.h" -exec realpath {} \;

Using find and xargs to list the timestamp of a file which has found from a containing string

I have to find a file from a given string inside and list this files timestamp only using find and xargs commands in linux command terminal
I've tried this code and it worked out but it gives error on ls command for long lines, need more smooth answer for this particular problem
find /home/stajyer -type f -exec grep -H 'ayberk' {} \; |xargs ls -l
Result:
ls: cannot access '/home/stajyer/myNameChangedFile/aFileInChangedFile4:ayberk': No such file or directory
ls: cannot access 'Binary': No such file or directory
ls: cannot access 'file': No such file or directory
ls: cannot access 'matches': No such file or directory
-rw------- 1 stajyer stajyer 9787 Haz 25 09:45 /home/stajyer/.bash_history
how can my code give less error corresponding to ls command?
From man xargs:
xargs reads
items from the standard input, delimited by blanks (which can be
protected with double or single quotes or a backslash) or newlines,
To disable that you can go with a zero delimetered stream and use -0 or --null option with xargs and -print0 with find. It would look like this:
find /home/stajyer -type f -exec grep -qH 'ayberk' {} \; -print0 | xargs -0 ls -l
Tested on repl.

Command to check for a very large number of .gz files in a directory [duplicate]

This question already has answers here:
Argument list too long error for rm, cp, mv commands
(31 answers)
Closed 5 years ago.
Below is the current days file. Previous days file converted to .gz by system. I wanted to find the total count of last days specific .gz files. I tried the below command which gives me the error. Please suggest
bash-3.2$ ls -lrth|tail
299K Mar 23 2017 N08170323091903766
333K Mar 23 2017 N08170323091903771
328K Mar 23 2017 N09170323091903776
367K Mar 23 2017 N09170323091903782
347K Mar 23 2017 N04170323092003784
368K Mar 23 2017 N08170323092003783
***bash-3.2$ ls -lrth N08170322*|wc -l***
bash: /usr/bin/ls: Arg list too long
0
***bash-3.2$ zcat N08170322*.gz|wc -l***
bash: /usr/bin/zcat: Arg list too long
0
This is happening because you have too many files in the directory.
You can easily get around the first issue:
ls | grep -c N08170322
or, to be even more precise:
ls | grep -c '^N08170322'
would give you the list of files. However, a better way to do this is:
find . -name "N08170322*" -exec ls {} + | wc -l
which will address the ls parsing issue mentioned in #hek2mgl's comment.
If you really want to count the lines of all the zipped files in one shot, you can do this:
find . -name "N08170322*" -exec zcat {} + | wc -l
See also:
Argument list too long error for rm, cp, mv commands
Use this
find . -name "N08170322*" -exec ls {} \; |wc -l
As explained in the below answer, you are getting argument list too long as there are multiple files in the directory. To overcome it, you can club it with find and exec
Edit: Created use case to check if command works with/without ls
These are the 3 empty files I created.
$ find -name "file*" -exec ls {} \;
./file1
./file2
./file3
Running wc -l without ls, prints number of lines in each file.
$ find -name "file*" -exec wc -l {} \;
0 ./file1
0 ./file2
0 ./file3
Running it with ls gives me number count of number of files, which is what OP wants.
$ find -name "file*" -exec ls {} \; | wc -l
3

What's the meaning of '{}' in a find command?

I want to know what the {} really does and how it works in this command:
find .-type f ! -name '*.c' -exec rm {} +
From man find:
-exec command ;
Execute command; true if 0 status is returned. All following
arguments to find are taken to be arguments to the command until an
argument consisting of ';' is encountered. The string '{}' is
replaced by the current file name being processed everywhere it
occurs in the arguments to the command, not just in arguments where it
is alone, as in some versions of find. Both of these constructions
might need to be escaped (with a '\') or quoted to protect them from
expansion by the shell.
and
-exec command {} +
This variant of the -exec action runs the specified command on
the selected files, but the command line is built by appending each
selected file name at the end; the total number of invocations of the
command will be much less than the number of matched files. The
command line is built in much the same way that xargs builds its
command lines. Only one instance of `{}' is allowed within the
command. The command is executed in the starting directory.
So what it does is to use the results of the find command as argument on the rm execution.
Then, the full command
find .-type f ! -name '*.c' -exec rm {} +
will look for files in the current directory structure. It will match those not having a name ending with .c. For all the results, it will execute the rm command, so all not *.c files will be removed.
Example:
$ find . -type f
./two/three
./something
$ find . -type f -exec ls -ltr {} +
-rw-rw-r-- 1 me me 0 Sep 30 11:37 ./something
-rw-r--r-- 1 me me 0 Nov 1 17:50 ./two/three

How can I add text to the same line?

I used this command to find mp3 files and write their name on log.txt:
find -name *.mp3 >> log.txt
I want to move the files using the mv command and I would like to append that to the log file so it could show the path where the files have been moved.
For example if the mp3 files are 1.mp3 and 2.mp3 then the log.txt should look like
1.mp3 >>>> /newfolder/1.mp3
2.mp3 >>>> /newfolder/2.mp3
How can I do that using unix commands? Thank you!
Using only move:
mv -v *.mp3 tmp/ > log.txt
or using find:
find -name '*.mp3' -exec mv -v {} test/ >> log.txt \;
You should probably use some scripting language like Perl or Python; text processing is rather awkward in the shell.
E.g. in Perl you can just postprocess the output of find, and print out what you did.
#!/usr/bin/perl -w
use strict;
use File::Find;
my #directories_to_search=("/tmp/");
sub wanted {
print "$File::Find::name >>> newdir/$_\n";
# do what you want with the file, e.g. invoke commands on it using system()
}
find(\&wanted, #directories_to_search);
Doing it in Perl or similar makes some things easier than in the shell; in particular handling of funny filenames (embedded spaces, special chars) is easier. Be careful when invoking syste() commands though.
For docs on the File::Find module see http://perldoc.perl.org/File/Find.html .
GNU find
find /path -type f -iname "*.mp3" -printf "%f/%p\n" | while IFS="/" -r read filename path
do
mv "$path" "$destination"
echo "$filename >>> $destination/$filename " > newfile.txt
done
output
$ touch 'test"quotes.txt'
$ ls -ltr
total 0
-rw-r--r-- 1 root root 0 2009-11-20 10:30 test"quotes.txt
$ mkdir temp
$ ls -l temp
total 0
$ find . -type f -iname "*\"*" -printf "%f:%p\n" | while IFS=":" read filename path; do mv "$filename" temp ; done
$ ls -l temp
total 0
-rw-r--r-- 1 root root 0 2009-11-20 11:53 test"quotes.txt

Resources