11

While using fish as my shell, i'm trying to set permissions on a bunch of c source files in current dir with

find . -type f -name "*.c" -exec chmod 644 {} +;

I get an error

find: missing argument to `-exec'

or

find . -type f -name "*.c" -exec chmod 644 {} \;

I get an error

chmod: cannot access '': No such file or directory

What's wrong?

6
  • 1
    try quoting the {} with "{}" or '{}' i.e. find . -type f -name "*.c" -exec chmod 644 '{}' + Aug 4, 2016 at 9:16
  • why the ; after + ?
    – Anthon
    Aug 4, 2016 at 9:20
  • @Anthon, if you only just arrived at this question, originally the OP posted the question without the ;, ie. .... chmod 644 {} + . Then Thomas Dickey posted his answer, then the OP edited to add the ; as you see it now. I know that still doesn't explain properly why the OP did it though... Aug 4, 2016 at 9:22
  • @the_velour_fog I reviewed the question from the first post queue, you don't see the answers there. The +; looks someone mixed up things from find's man page.
    – Anthon
    Aug 4, 2016 at 9:25
  • The semicolon at the end of the first command is just unnecessary but doesn't matter, both bash and fish eat it before passing the arguments to find
    – ilkkachu
    Aug 4, 2016 at 9:31

3 Answers 3

19

fish happens to be one of the few shells where that {} needs to be quoted.

So, with that shell, you need:

find . -type f -name '*.c' -exec chmod 644 '{}' +

When not quoted, {} expands to an empty argument, so the command becomes the same as:

find . -type f -name '*.c' -exec chmod 644 '' +

And find complains about the missing {} (or ; as + is only recognised as the -exec terminator when following {}).

With most other shells, you don't need the quotes around {}.

2
  • @Rahul Agreed. Can I change it to this answer?
    – Darc Nawg
    Aug 4, 2016 at 9:38
  • I found this same trouble after much time trying to deal with git stashes O_o
    – Pysis
    Aug 4, 2016 at 17:25
3

{ and } have special meanings in fish. They need to be escaped in order to work with find, for example:

find . -type f -name "*.c" -exec chmod 644 \{\} \;

Or you would have to quote {} like,

find . -type f -name "*.c" -exec chmod 644 '{}' \;
4
  • 1
    I tried escaping for the "+" and it didn't work (perhaps version-dependent). The single quotes work. Aug 4, 2016 at 9:20
  • @ThomasDickey find . -type f -name "*.c" -exec chmod 644 \{\} +; seems to work as well in fish.
    – Darc Nawg
    Aug 4, 2016 at 9:26
  • 1
    It only works if you cut/paste. If you attempt to edit the line, it gets confused and breaks badly. Aug 4, 2016 at 19:25
  • @ThomasDickey I am completely agree with you. I haven't tried the command before posting it.
    – Rahul
    Aug 5, 2016 at 9:51
3

Your examples miss the expected trailing semicolon:

find . -type f -name "*.c" -exec chmod 644 {} \;

After revising the question, it is "fish" shell. This is a known issue which can be worked around using quoting as @rahul noticed. However, the escaping suggested does not work for my configuration: single quoting does:

find . -type f -name "*.c" -exec chmod 644 '{}' \;
find . -type f -name "*.c" -exec chmod 644 '{}' +

What does happen (if one types the characters rather than cut/paste) is that on trying to edit the command-line to escape the curly braces, fish gets confused and cannot proceed. Here's a screenshot just after inserting the backslashes (no point in trying to cut/paste that):

editing the command-line

and then pressing return:

just press return

So no, fish doesn't really work with escaped curly braces. It only pretends to do that. Continuing to press enter gives a conclusive demo:

q.e.d.

Further reading:

6
  • but the what is wrong with the first expression ?
    – Rahul
    Aug 4, 2016 at 9:12
  • 1
    I don't get an error with that. OP may be confused with the latter. Aug 4, 2016 at 9:13
  • With the above example I get chmod: cannot access '': No such file or directory
    – Darc Nawg
    Aug 4, 2016 at 9:14
  • I am using fish shell.
    – Darc Nawg
    Aug 4, 2016 at 9:15
  • Looks like fish is pre-interpreting the find command (and only knows about the second case). I'll take a quick look for source to clarify this. Aug 4, 2016 at 9:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .