Linux Find command- exclude find based on file name - linux

I feel like this is a ridiculously easy question but I cannot find a simple regex answer for this. Basically, I am trying to use find to get a list of all files in my system with some exclusions. One of these exclusions is any file that ends in .Foo.cs, or any file named FooInfo.cs. I have successfully excluded a couple directories from my search, but cannot seem to exclude these two files. I've tried using -name, but would -name even work for this? Below is my expression. Thanks.
find . ! -name 'FooInfo.cs' ! -name '*.Foo.cs' -type d \( -name Foo-o -name 2Foo -o -name 2_Foo \) -prune -o -type f ! -size 0 \( -name "*.java" -o -name "*.cs" -o -name "*.cpp" -o -name "*.cxx" -o -name "*.cc" -o -name "*.c" -o -name "*.h" -o -name "*.scala" -o -name "*.css" -o -name "*.html" -o -name "*.bat" -o -name "*.js" \) -exec realpath {} \;| xargs grep -L CUSTOMERINFO | sed -e 's/$/\r/g' >> ../output.txt

So I'm not sure why, but I ended up fixing this by changing the order of what I'm excluding. Instead of excluding at the very beginning, the following worked (moving the ! -name '.FOO.cs' and ! -name '.fooinfo.cs' to right after the declaration type -f).
I'm assuming this worked because they are files so they must be flagged with type -f. But please comment and correct below if you know why.
find . -type d \( -name Foo-o -name 2Foo -o -name 2_Foo \) -prune -o -type f ! -size 0 ! -name 'FooInfo.cs' ! -name '*.Foo.cs' \( -name "*.java" -o -name "*.cs" -o -name "*.cpp" -o -name "*.cxx" -o -name "*.cc" -o -name "*.c" -o -name "*.h" -o -name "*.scala" -o -name "*.css" -o -name "*.html" -o -name "*.bat" -o -name "*.js" \) -exec realpath {} \;| xargs grep -L CUSTOMERINFO | sed -e 's/$/\r/g' >> ../output.txt

Related

Find Command with multiple file extensions

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 {} +

'Sed' not working on result of 'find' with multiple parameters

I'm trying to do a find and replace function, finding files which match a criteria then find/replace text within them.
Find statement (works find and returns list of files):
find / -type f -name "*.properties" -o -name "*.xml" -not \( -path '/tmp/*' -o -path '/var/tmp/*' \)
Sed find/replace:
sed -i 's/find/replace/g' {} \;
Putting together:
find / -type f -name "*.properties" -o -name "*.xml" -not \( -path '/tmp/*' -o -path '/var/tmp/*' \) -exec sed -i 's/10\.32\.19\.156/10.32.19.165/g' {} \;
However this does not seem to work. Removing some 'find' parameters causes it to work, for example this works:
find / -type f -name "*.properties" -exec sed -i 's/10\.32\.19\.156/10.32.19.165/g' {} \;
How can I get sed to work with the extended 'find' parameters?
Currently these two 'find' statements return exactly the same result in a test folder with only 2 files:
find /var/tmp/ipreplace/ -type f -name "*.properties"
find /var/tmp/ipreplace/ -type f -name "*.properties" -o -name "*.xml" -not \( -path '/tmp/*' -o -path '/var/tmp/*' \)
I guess the use of -path parameter in your find command is wrong.
Try the following:
find / -not \( -path '/tmp' -prune \) -not \( -path '/var/tmp' -prune \) -type f -name "*.properties" -o -name "*.xml" -exec sed -i 's/10\.32\.19\.156/10.32.19.165/g' {} \;
Look at this post for reference

Moving photos and renaming them if they exist?

I'm trying to move photos from directories to one directory with find. It works good:
find /origin/path \( -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.JPG' -o -iname '*.JPEG' -o -iname '*.PNG' -o -iname '*.png' -o -iname '*.gif' -o -iname '*.GIF' \) -type f -exec mv -nv -t /final/path -- {} +;
How to rename files if they have the same name (but different photos)?
You can use the --backup=t option for mv. This will append an increasing numbered suffix to files whose target already exists.
$ find /tmp/test -type f
/tmp/test/dir2/image.jpg
/tmp/test/dir3/image.jpg
/tmp/test/dir1/image.jpg
/tmp/test/dir4/image.jpg
$ mkdir /tmp/test2
$ find /tmp/test -iname '*.jpg' -print0 | xargs -0 mv -v --backup=t --target-directory=/tmp/test2
‘/tmp/test/dir2/image.jpg’ -> ‘/tmp/test2/image.jpg’
‘/tmp/test/dir3/image.jpg’ -> ‘/tmp/test2/image.jpg’ (backup: ‘/tmp/test2/image.jpg.~1~’)
‘/tmp/test/dir1/image.jpg’ -> ‘/tmp/test2/image.jpg’ (backup: ‘/tmp/test2/image.jpg.~2~’)
‘/tmp/test/dir4/image.jpg’ -> ‘/tmp/test2/image.jpg’ (backup: ‘/tmp/test2/image.jpg.~3~’)
$
sorry i didn't because i'm on windows now, but below script should do it
files_list=$(find /origin/path \( -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.JPG' -o -iname '*.JPEG' -o -iname '*.PNG' -o -iname '*.png' -o -iname '*.gif' -o -iname '*.GIF' \) -type f)
for file in ${files_list}
do
counter=0
while true
do
if [[ ! -a ${file} ]]
then
mv "${file}" "/final/path/${file}"
break
else
file="${file}${counter}"
(( counter++ ))
fi
done
done

linux find prune

I am trying to exclude two directories; vntvdone and downloading, but for some reason, my command still goes in there and outputs the file within it:
find -name '*.avi' -o -name '*.mkv' -o -name '*.mp4' -o -name '*.VOB' -o -path './downloading' -prune -o -path './vntvdone' -prune
I am also running into problems where if a folder/directory that has .mp4 in it, it also gets treated as a file as well... how can we do this search only for files and not folders?
I find it easier to use ! than use prune. I've assumed the starting path for find is '.' The example omits it.
find . \( -type d -a ! -name 'downloading' -a ! -name 'vntdone' -a ! -name '.' \) -o -name \*.avi -o -name \*.mkv -o -name \*.mp4 -o -name \*.VOB

find all but skip one folder

I have a command that looks through all my sub folders for files, however I want it to skip a folder from the search and I'm not sure what is the right way to do this:
find -name '*.avi' -o -name '*.mkv' -o -name '*.mp4' -o -name '*.vob'
I want it to not look into the folder name: secure
I tried:
find -name '*.avi' -o -name '*.mkv' -o -name '*.mp4' -o -name '*.vob' --skip 'secure'
but it does not work.
Thanks for your help in advance.
There is no --skip argument in GNU find. But you can do what you want using the -path and -prune expressions. The syntax is a little weird: you use -path ./secure -prune as a term which you then OR with the rest of the expression. So in your case:
find . -name '*.avi' -o [...] -o -path ./secure -prune
Note that this will still return the directory ./secure in the results, but nothing inside it.
What about the following?
find \( -name '*.avi' -o -name '*.mkv' -o -name '*.mp4' -o -name '*.vob' \) -a -not -path './secure*'

Resources