10

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

18

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.