0

I am writing a script which takes a directory name from user, then find files inside it. The script may fail if the user use some special characters with their directory name.

$ var="-foobar";
$ find "$var";
find: unknown predicate `-foobar'

For a lot of commands, it is easy to avoid the problem by giving -- to indicate that it is an end of options. But it does not with with find:

$ find -- "$var";
find: unknown predicate `-foobar'

What should I do to handle directory with unpredictable characters?

Livy
  • 455
  • 4
  • 10
  • 1
  • Since I don't know the path given by the user will be relative (-foobar) or absolute (/tmp/-foobar), just preceeding it with ./ is not safe. I guess the solution to handle this would be: find $(realpath -- "$var").

    Thanks for your suggestion.

    – Livy Sep 03 '19 at 04:08
  • Formally -- does work to indicate the end of options. Compare find -L . and find -- -L . POSIX defines -H and -L as options, nothing more. Implementations may add few options, but still paths and expression are not options. – Kamil Maciorowski Sep 03 '19 at 04:09
  • Your solution with realpath won't help if you want relative paths to stay relative. I mean you may want find to print/use -foobar/baz or ./-foobar/baz, not /home/livy/-foobar/baz. I can imagine scenarios where this matters. Consider find "$(printf '%s\n' "$var" | sed '1 s|^-|./-|')". – Kamil Maciorowski Sep 03 '19 at 06:07
  • What OS are you using here? – Mark Plotnick Sep 03 '19 at 06:43
  • @MarkPlotnick I'm using Ubuntu server. What are the scenarios you are talking about? I am not familiar with sed command and don't understand it. – Livy Sep 03 '19 at 06:48
  • Thanks, I will try to reproduce your issue. @KamilMaciorowski was the one who mentioned sed. – Mark Plotnick Sep 03 '19 at 07:17
  • 1
    Scenarios? E.g. you may want to use the results in the context of another (semi-mirrored) directory; like find some files here, delete corresponding files there. Or use the results with tar without full paths (this). About sed: sed '1 s|^-|./-|' will replace - at the very beginning of the first line with ./-. Input without leading - is unaffected. The "first line" condition may seem excessive but note a name like -a\n-b (where \n denotes the newline character) is a valid name in general. You don't want to alter the second line. – Kamil Maciorowski Sep 03 '19 at 07:38

0 Answers0