When git runs my post-receive hook, I'd like it to run all the scripts in the subdirectory post-receive.d.

My script is as follows

DIR="$( dirname "$SOURCE" )"

for SCRIPT in $DIR/post-receive.d/*
  if [ -f "$SCRIPT" -a -x "$SCRIPT" ] 

Source: https://github.com/alexchamberlain/githooks/blob/master/post-receive

Is this secure? Reliable?

I can foresee one problem. The hook supplies data using stdin, which should be copied to each subscript. I'm pretty sure this isn't happening at the moment. Any ideas?

  • \$\begingroup\$ test -x "$file" or [[ -x "$file" ]] is the only test you need; a file doesn't need to be readable to be executable. \$\endgroup\$
    – DopeGhoti
    Feb 28 '14 at 19:49
for SCRIPT in $DIR/post-receive.d/*

You might want to limit that to only *.sh pattern, just for clarity.

Personally I'm a fan of the one-line-style, but that's personal preference:

for ITEM in SET; do
if [ CONDITION ]; then

And yes, input from stdin is at the moment ignored completely by your script. Reading from stdin can be done via the read command, like this.


# This whill be our input variable

# Read the first line without adding
# a new line to the start.
read input

# Start reading from stdin
while read line; do
    # Concate the input into our variable

# Echo it...what else?
echo $input

After doing that you can pipe the variable into the scripts like this:

echo $INPUT | "$SCRIPT"

One word of warning: I'm not sure if this is BASH only or cross-shell compatible.

  • 3
    \$\begingroup\$ Use More Quotes™ and watch out for newlines - printf %s "$input" | "$SCRIPT". Your while loop will drop the last line of input if it's not followed by a newline and treats backslashes specially - while IFS=$'\n' read -r line || [[ -n "$line" ]]; do \$\endgroup\$
    – l0b0
    Sep 11 '12 at 11:34

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.