package picocli.examples.passthrough; import picocli.CommandLine; import picocli.CommandLine.Command; import picocli.CommandLine.Option; import picocli.CommandLine.Parameters; import picocli.CommandLine.Unmatched; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.Callable; @Command(name = "find") public class Find implements Callable { enum FileType { b, c, d, l, p, f, s, D, } @Option(names = "-type", split = ",", description = {"The file type to search for. Valid values are: ${COMPLETION-CANDIDATES}, where:", "b block (buffered) special", "c character (unbuffered) special", "d directory", "p named pipe (FIFO)", "f regular file", "l symbolic link; this is never true if the -L option or" + "the -follow option is in effect, unless the symbolic link is broken. " + "If you want to search for symbolic links when -L is in effect, use -xtype.", "s socket", "D door (Solaris)", "To search for more than one type at once, you can supply the combined list " + "of type letters separated by a comma `,' (GNU extension)."}) List types = new ArrayList(Arrays.asList(FileType.c)); @Option(names = "-exec", arity = "*", description = "Execute command; true if 0 status is returned. All following arguments " + "to `find` are taken to be arguments to the command until an argument " + "consisting of `;' is encountered. The string `{}' is replaced by the " + "current file name being processed everywhere it occurs in the arguments " + "to the command, not just in arguments where it is alone, as in some " + "versions of find. Both of these constructions might need to be escaped " + "(with a `\\') or quoted to protect them from expansion by the shell. " + "See the EXAMPLES section for examples of the use of the -exec option. " + "The specified command is run once for each matched file. " + "The command is executed in the starting directory. " + "There are unavoidable security problems surrounding use of the -exec action; " + "you should use the -execdir option instead.") List execCommandAndArgs; @Parameters(index = "0") File startingPoint; @Unmatched List unmatched; @Override public Integer call() throws Exception { System.out.printf("Finding files of type %s, startingPoint: %s, invoking command '%s' on each...%n", types, startingPoint, execCommandAndArgs); System.out.printf("Unmatched positional arguments following ';' were: %s%n", unmatched); return 0; } public static void main(String[] args) { //args = ". -type d -exec ls -la {} ;".split(" "); //args = ". -type d -exec ls -la {} +".split(" "); // args = ". -type d -exec ls -la {} -- this is unmatched".split(" "); args = ". -type d -exec ls -la {} ; this is unmatched".split(" "); // exposes the bug int exitCode = new CommandLine(new Find()) .setEndOfOptionsDelimiter(";") .execute(args); } }