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.