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
  • 445
  • 4
  • 10
  • 1
    See the [*second* answer](https://unix.stackexchange.com/a/1529/73093). – Michael Homer Sep 03 '19 at 04:01
  • 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](https://stackoverflow.com/q/18681595/10765659)). 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