Find Command with multiple file extensions - linux

I'm looking through many sub directories and finding all the files ending in .JPG .jpg and .png and copying them to a separate directory, however just now its only finding .JPG
Could someone explain what i'm doing wrong?
find /root/TEST/Images -name '*.png' -o -name '*.jpg' -o -name '*.JPG' -exec cp -t /root/TEST/CopiedImages {} +

You have to group the -o conditions because -a, the implied AND between the last -name '*.JPG' and -exec has higher precedence:
find /root/TEST/Images \( -name '*.png' -o -name '*.jpg' -o -name '*.JPG' \) -exec cp -t /root/TEST/CopiedImages {} +
Grouping is done with parentheses, but they have to be escaped (or quoted) due to their special meaning is shell.
Unrelated to this, you can shorten the overall expression by combining filters for jpg and JPG with the case-insensitive -iname (as noted in comments):
find /root/TEST/Images \( -name '*.png' -o -iname '*.jpg' \) -exec cp -t /root/TEST/CopiedImages {} +

Related

How to Find Recent or Today’s Modified Files in Linux

I have a requirement that will have to find out latest modified files list along with date and time.
mainly we have 2 files that boot.properties and ldap related files as part of beadmin password change activity.
find /target_directory -type f -name "*boot.properties" -exec ls -ltr {} \;
is giving only boot.properties but I need to find other files which is in different location.
find supports multiple path arguments, so you could do something like
find /target_dir /other -type f \( -name "*boot.properties" -o -name "other*" \) -exec ls -ltr {} +
try something like this if you have different location and file names.
find /root_directory \
\( \( \
-path "/target_directory1/*" -type f -name "*boot.properties" \) -o \( \
-path "/target_directory2/*" -type f -name "*boot2.properties" \
\) \) -exec ls -ltr {} \;
also, you have other options to find by modified date too.
check this article
https://www.cyberciti.biz/faq/linux-unix-osxfind-files-by-date/

Find different types of files and move to a specific directory

Finding *.mkv and *.mp4 works
find /home6/movies/ -name '*.mp4' -o -name '*.mkv'
but moving them for some reason partially fails and moves only mkv files
find /home6/movies/ -name '*.mp4' -o -name '*.mkv' -exec mv {} /home6/archive/ \;
Am I using an incorrect find switch "-o" for this task?
Looks like you need to surround the or expression in parentheses so the exec applies to both matches.
This is a similar question: `find -name` pattern that matches multiple patterns
find /home6/movies/ \( -name '*.mp4' -o -name '*.mkv' \) -exec mv {} /home6/archive/ \;

FInd patternf for multiple pattern of files

I need to search for multiple pattern of files and check their mtime and if it morethan 30 days then delete all the files. I am using the below command but it's deleting only one pattern of file and not all. Kindly let me know where is the mistake in my command.
find /root -type f \( -name "*.tgz" -o -name "*.bz2" \) -mtime +30 -print -exec rm '{}' +
Try escaping parentheses in the command and adding a wildcard character:
find /root -type f \( -name "*.tgz" -o -name "*.bz2" \) -mtime +30 -exec rm {} \+

cscope for files which are symlinks

I have a source directory with several files. Some of them are symlinks to other files.
I created a cscope.files file. But when I execute cscope. It complains for the files that are symlinks:
cscope: cannot find file /home/bla/source/file.cc
I think it's not very good, but maybe the correct way to go is to change the "find" script, to just write the destination of the symlink instead?
Currently I'm using:
# Write only the files which are NOT symlinks
find `pwd` \( \( -iname "*.c" -o -iname "*.cc" -o -iname "*.h" \) -and \( -not -type l \) \) -print > cscope.files
# Add the target of the symlink for all files matching the right extension, and are symlinks
find `pwd` \( \( -iname "*.c" -o -iname "*.cc" -o -iname "*.h" \) -and -type l \) -printf "%l\n" >> cscope.files
But this seems like a terrible solution. Still looking for a better one
I think you can use the command to find all real paths in a folder that you searched
find -L [your searched folder] -name [your searched pattern] -exec realpath {} \; >> cscope.files
For example, if I would like to add developed folder and linux kernel header to cscope.files, I will the these commands:
find -L `pwd` -iname "*.c" -o -iname "*.h" > cscope.files
find -L /usr/src/linux-headers-3.19.0-15-generic/ -iname '*.h' -exec realpath {} \; >> cscope.files
I hope the answer can help you.
For example if you want to give / as your path for cscope, and want cscope to search files with extensions .c/.h/.x/.s/.S you can give the find command as:
find / -type f -name "*.[chxsS]" -print -exec readlink -f {} \;> cscope.files
This will include regular files, including targets of symbolic links.
I just do the following to avoid symbolic links, as well get the absolute path in the cscope.files. With absolute path you can search from any directory in your sandbox when cscope is integrated with the vim editor
find /"path-to-your-sandbox" -path .git -prune -o -name "*.[ch]" -exec readlink -f {} \; > cscope.files
Note: if you omit -print from the find it does not put the symbolic link path in your cscope.files only the resolved path.
Better in a bash script:
#!/bin/bash
#
# find_cscope_files.sh
extension_list=(c cpp cxx cc h hpp hxx hh)
for x in "${extension_list[#]}"; do
find . -name "*.$x" -print -exec readlink -f {} \;
done
For reference for others I'm currently using.
find "$(pwd)" \( -name "*.[chCS]" -o -name "*.[ch][ci]" -o -name "*.[ch]pp" -o -name "*.[ch]++" -o -name "*.[ch]xx" ) -not \( -ipath "*unittest*" -or -ipath "*regress*" \) \( \( -type l -xtype f -exec readlink -f {} \; \) -o \( -type f -print \) \) >cscope.files
cscope -q -R -b -i cscope.files

How can I make find pass file names to exec without the leading directory name?

Someone created directories with names like source.c. I am doing a find over all the directories in a tree. I do want find to search in the source.c directory, but I do not want source.c to be passed to the grep I am doing on what is found.
How can I make find not pass directory names to grep? Here is what my command line looks like:
find sources* \( -name "*.h" -o -name "*.cpp" -o -name "*.c" \) -exec grep -Hi -e "ThingToFind" {} \;
Add -a -type f to your find command. This will force find to only output files, not directories. (It will still search directories):
find sources* \( -name "*.h" -o -name "*.cpp" -o -name "*.c" \) -a -type f -exec grep -Hi -e "ThingToFind" {} \;

Resources