2

Finding files based on different names I know how to do. The problem is that I don't know how delete all of them at once. I am using OMVS in z/OS390.

To find files searching by different extensions I am successfully doing:

find . -name "*.xml" -o -name "*.ipm" -type f

To delete files after searched by only one name, I am successfully doing:

find . -name "*.xml" -type f -exec rm -iv {} \;

Well, if I mixed both ideas, I get deleted only files found by the last -name:

find . -name "*.xml" -o -name "*.ipm" -type f -exec rm -iv {} \;

In this case, it seems the files matched the first pattern (*.xml) aren't affected by -exec rm.

After searching around, I guessed that the problem is that I have to "hold" all names found before executing the rm. I tried three approaches without success...

First attempt:

$ find . -name "*.xml" - o -name "*.ipm" -type f -print0 | xargs -0
FSUM6372 Unknown option "-"
Usage: find directory ... expression
xargs: FSUM6001 Unknown option "-0"

Usage: xargs Ý-l#¨Ý-L #¨ Ý-irepl¨Ý-I repl¨ Ý-n#¨ Ý-tpx¨ Ý-s#¨ Ý-eeof¨Ý-E eof¨ Ýc
md Ýargs ...¨¨

Second attempt:

$ find . (-name "*.xml" - o -name "*.ipm") -type f
FSUM7332 syntax error: got (, expecting Newline

Third attempt:

$ find . -type f \(-name "*.xml" -o -name "*.ipm"\)
FSUM6372 Unknown option "(-name"
Usage: find directory ... expression
Kusalananda
  • 333,661
Jim C
  • 145
  • don_crissti, taliezin, Raphael Ahrens, jsbillings, Jeff Schaller, could you please show me the other question? I really searched for and I didn't find it here. – Jim C Jun 01 '16 at 16:46
  • don_crissti, taliezin, Raphael Ahrens, jsbillings, Jeff Schaller, kindly, while voting my question as duplicated, note that I was using the correct commands as many foruns/threads show but I missed the concept well-explained below that I should add spaces between ( and -. Honestly, I didn't find other person facing exact same issue with same scenario and I included above all alternatives I have found so far. To sum up, please, can you show in http://unix.stackexchange.com/questions/102191/find-with-multiple-name-and-exec-executes-only-the-last-matches-of-nam the explanation about the spaces? – Jim C Jun 01 '16 at 16:55

2 Answers2

3

Your parenthesis attempt lacked spaces around them so find saw an option called (-name and didn't know what to do with it. Instead, add spaces around the parens like:

find . \( -name "*.xml" -o -name "*.ipm" \) -type f -exec rm -iv {} \;

Also, if you have GNU find you can use -delete instead of the -exec rm -iv {} \;

As Wildcard noted, since we're doing a command that can take a list of arguments we can save some processes (perhaps a lot depending on how often it matches) by using + to terminate -exec instead of \;. With + the -exec will collect the paths into sets and apply them with a single invocation of the application (here rm) instead of invoking the application once for each path. So if you don't have or don't want to use -delete the more efficient solution is to do it as:

find . \( -name "*.xml" -o -name "*.ipm" \) -type f -exec rm -iv {} +
Eric Renouf
  • 18,431
  • 1
    And whether you have GNU find or not you can turn the \; at the end to + to spawn fewer invocations of rm. – Wildcard Jun 01 '16 at 01:28
  • Very nice information about find's '+' option. I didn't know about it. Looks like it replaces the need for piping to xargs. – Johan Boulé Jun 03 '16 at 08:03
2

Using parenthesis works, but you need to escape them so the shell does not interpret them as subshell invocations. You can use backslash, \( and \) or quotes.

If none of your files have names that contain newlines or other control characters, which should be the case unless someone tries to be nasty, then you can use the pipe to xargs approach, which is the fastest, without the -print0 and -0 options.