1

I have a rather complex set of files to be found and reacted upon (e.g. paths copied to a text file):

For example:

 find / \( -iname "*ssh*" -or -iname "*scp*" \) \( -not -path -"/run" -not -path "/rw/*" -and -not -path "/home/*" -and -not -path "*/qml/*" \) >> ~/files.txt

Here I want to find all files or folders that are related to "ssh" and "scp" but not in /run or in /rw directories.

I will be adding more conditions to this, but the commands gets so long. How can I do this with regex?

2 Answers 2

5

Best would be not to descend at all in those directories you want to exclude rather than filtering out the files in there after the fact with ! -path <pattern>:

LC_ALL=C find / \
       '(' \
          -path /run -o  -path /rw -o -path /home -o -path '*/qml' \
       ')' -prune -o '(' \
          -name '*[sS][hH][hH]*' -o -name '*[sS][cC][pP]*' \
       ')' -print

Here using POSIX find syntax. With GNU find, that could be:

LC_ALL=C find / -regextype posix-extended \
  -regex '/home|/rw|.*/qml' -prune -o \
  -iregex '.*s(cp|sh)[^/]*' -print

With BSD find, you just use -E like in grep or sed to get POSIX EREs:

LC_ALL=C find -E / \
  -regex '/home|/rw|.*/qml' -prune -o \
  -iregex '.*s(cp|sh)[^/]*' -print
3

Here's a version with line breaks that's a bit easier to read, and with some typo fixes. I'm assuming GNU find, but minor modifications will work with most BSD finds as well.

find / \
     \( -iname "*ssh*" -or -iname "*scp*" \) \
     \( -not -path "/run/*" \
        -not -path "/rw/*" \
        -not -path "/home/*" \
        -not -path "*/qml/*" \) \
     >> ~/files.txt

Now to simplify it a bit, -iname "*ssh*" -or -iname "*scp*" can be written as a regex like

find ... \
     -regextype posix-extended \
     -iregex '.*(ssh|scp)[^/]*' \
     ...

and you can now more easily add extra names like (ssh|scp|rsync|...).

The -not -path tests can be combined into a regex like this:

find ... \
     -not -regex '(/run|/rw|/home|.*/qml)/.*'

but find will still waste a lot of time exploring those directories unless you use -prune:

find / \
     -regextype posix-extended \
     -not \( -regex '(/run|/rw|/home|.*/qml)/.*' -prune \) \
     -iregex '.*(ssh|scp)[^/]*' \
     >> ~/files.txt

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.