Home > Blockchain >  Use Find and xargs to delete dups in arraylist
Use Find and xargs to delete dups in arraylist

Time:04-01

I have arraylist of files and I am trying to use rm with xargs to remove files like:

    dups=["test.csv","man.csv","teams.csv"]

How can I pass the complete dups array to find and delete these files?

I want to make changes below to make it work

    find ${dups[@]} -type f -print0 | xargs -0 rm

CodePudding user response:

Your find command is wrong.

# XXX buggy: read below
find foo bar baz -type f -print0

means look in the paths foo, bar, and baz, and print any actual files within those. (If one of the paths is a directory, it will find all files within that directory. If one of the paths is a file in the current directory, it will certainly find it, but then what do you need find for?)

If these are files in the current directory, simply

rm -- "${dups[@]}"

(notice also how to properly quote the array expansion).

If you want to look in all subdirectories for files with these names, you will need something like

find . -type f \( -name "test.csv" -o -name "man.csv" -o -name "teams.csv" \) -delete

or perhaps

find . -type f -regextype egrep -regex '.*/(test\.csv|man\.csv|teams\.csv)' -delete

though the -regex features are somewhat platform-dependent (try find -E instead of find -regextype egrep on *BSD/MacOS to enable ERE regex support).

Notice also how find has a built-in predicate -delete so you don't need the external utility rm at all. (Though if you wanted to run a different utility, find -exec utility {} is still more efficient than xargs. Some really old find implementations didn't have the syntax for -exec but you seem to be on Linux where it is widely supported.)

Building this command line from an array is not entirely trivial; I have proposed a duplicate which has a solution to a similar problem. But of course, if you are building the command from Java, it should be easy to figure out how to do this on the Java side instead of passing in an array to Bash; and then, you don't need Bash at all (you can pass this to find directly, or at least use sh instead of bash because the command doesn't require any Bash features).

I'm not a Java person, but from Python this would look like

import subprocess

command = ["find", ".", "-type", "f"]
prefix = "("
for filename in dups:
    command.extend([prefix, "-name", filename])
    prefix = "-o"
command.extend([")", "-delete"])
subprocess.run(command, check=True, encoding="utf-8")

Notice how the backslashes and quotes are not necessary when there is no shell involved.

  •  Tags:  
  • bash
  • Related