Home > Mobile >  Strange behavior with bash find command
Strange behavior with bash find command

Time:07-27

Here is my slowread.sh script:

#!/bin/bash
sleep 1
cat $1

Now look this find command:

find /tmp/*.txt -exec slowread.sh {} \;

this find command works perfectly. It displays 10 files (because i have 10 .txt files in /tmp)

Now look at this find command:

find /tmp/*.txt -exec slowread.sh {}  

With the " " instead of "\;", the find command only displays the first file ! My question is... why ?

Thanks

CodePudding user response:

From the man page of find:

        -exec command {}  
              This variant of the -exec action runs the specified
              command on the selected files, but the command line is
              built by appending each selected file name at the end; the
              total number of invocations of the command will be much
              less than the number of matched files.  The command line
              is built in much the same way that xargs builds its
              command lines.  Only one instance of `{}' is allowed
              within the command, and it must appear at the end,
              immediately before the ` '; it needs to be escaped (with a
              `\') or quoted to protect it from interpretation by the
              shell.  The command is executed in the starting directory.
              If any invocation with the ` ' form returns a non-zero
              value as exit status, then find returns a non-zero exit
              status.  If find encounters an error, this can sometimes
              cause an immediate exit, so some pending commands may not
              be run at all.  For this reason -exec my-
              command ... {}   -quit may not result in my-command
              actually being run.  This variant of -exec always returns
              true.

Your script calls cat $1 which outputs the contents of the first argument, but your second example is calling your script one time with multiple arguments. The remaining arguments are being ignored because your script doesn't reference them at all. The first example works because it calls your script 10 times with a single argument per invocation.

If you want to support the find -exec {} case, you should change your script to run cat "${@}" which will output the contents of all the arguments passed to the script.

Or, if you want to sleep between each file, you can process them in a loop:

#!/bin/bash
for arg ; do
  sleep 1
  cat "${arg}"
done
  • Related