0

Here's what I'm trying to do:
I have several git repos. I want to setup a push-to-deploy script for each of them. being so lazy to do that for each and every repo, I wanted to script it.

My script generates a post-receive file for each repo.

#!/bin/bash

REPOS=/var/opt/gitlab/git-data/repositories/user

for i in $(ls $REPOS)
do
        DEPLOY_DIR=/home/user/public_html/"$i"/
        POST_RECEIVE_DIR=$REPOS/"$i".git/hooks/post-receive

        echo -e '
from, to, branch = ARGF.read.split " "\r
\r
 # 3. Copy files to deploy directory\r
deploy_to_dir = File.expand_path('$DEPLOY_DIR')\r
`GIT_WORK_TREE="#{deploy_to_dir}" git checkout -f master`\r
puts "DEPLOY: master(#{to}) copied to '#{deploy_to_dir}'"\r
' > $POST_RECEIVE_DIR
        chmod +x $POST_RECEIVE_DIR

done

Notice that the only part that changes in the generated file is where $DEPLOY_DIR lies.
And $DEPLOY_DIR changes with each iteration.
The problem is: ALL the generated files have the LAST value of $DEPLOY_DIR.

To debug I tried to echo the variable values in various places in the script and they all produce the desired outputs. I thought it could be a problem with the buffers not being flushed. so I tried to use the sync command. I tried using cat instead of echo. I tried to pass the file as a parameter to a python script where I write to the file and flush the buffer.

All failed to work.

3
  • Useless use of $(ls $REPOS). Better would be: for i in $REPOS/*.
    – iamauser
    Commented Jan 1, 2016 at 18:42
  • @iamauser - how is that better?
    – mikeserv
    Commented Jan 1, 2016 at 19:19
  • Have you tried to write to one of these files manually, and see if all of them change? They may all be symbolic links to the same file. Otherwise, I would suggest you edit your answer, and try to walk us through creating a minimal scenario to reproduce the error.
    – Amir
    Commented Jan 1, 2016 at 20:05

2 Answers 2

1

The answer is hidden in your question.

 echo $variable > file in a loop outputs only the last value of variable

will obviously output the last value only.

instead the answer is

echo $variable >> file in a loop outputs all the values of variable

> overwrites a value while >> appends it. Therefore , if you are using only > in a loop , it will keep overwriting , and only the last value will be there in the file at the end

     ijaz@ijaz-HP-EliteBook-8560p:~$ echo hi>test1
     ijaz@ijaz-HP-EliteBook-8560p:~$ cat test1
     hi
     ijaz@ijaz-HP-EliteBook-8560p:~$ echo hello>test1
     ijaz@ijaz-HP-EliteBook-8560p:~$ cat test1
     hello
     ijaz@ijaz-HP-EliteBook-8560p:~$ echo hello1>>test1
     ijaz@ijaz-HP-EliteBook-8560p:~$ cat test1
     hello
     hello1
     ijaz@ijaz-HP-EliteBook-8560p:~$ 
6
  • this is incorrect - both forms output all values. at least, both forms do after first interpreting those values for $IFS splitting and shell globs by default, and, for a standard echo, for \\ backslash escapes as well.
    – mikeserv
    Commented Jan 1, 2016 at 19:23
  • no , a single > in loop will overwrite the old value by the new one
    – Ijaz Ahmad
    Commented Jan 1, 2016 at 19:24
  • indeed - it cant do that without output.
    – mikeserv
    Commented Jan 1, 2016 at 19:25
  • that's good. now can you do something about the $IFS, shell glob and echo backslash interpretations?
    – mikeserv
    Commented Jan 1, 2016 at 19:33
  • This answer addresses the OP’s title, but not the actual question. If you look closely, you will see that each time OP uses >, it’s writing to a different file, and all the files end up undesirably having the same contents.
    – Amir
    Commented Jan 1, 2016 at 20:13
0

It seems to me that you have a quoting error somewhere.

Try using a "here document" to output the script:

    cat <<__EOF >"$POST_RECEIVE_DIR"
from, to, branch = ARGF.read.split " "

# 3. Copy files to deploy directory
deploy_to_dir = File.expand_path('$DEPLOY_DIR')
GIT_WORK_TREE="#{deploy_to_dir}" git checkout -f master
puts "DEPLOY: master(#{to}) copied to '#{deploy_to_dir}'"
__EOF

Also, what's with the \rs? Are you trying to write DOS files?

3
  • echo doesnt read stdin. it echoes arguments.
    – mikeserv
    Commented Jan 1, 2016 at 18:17
  • Sorry, should have used cat. Will edit the answer.
    – Beat Bolli
    Commented Jan 1, 2016 at 18:31
  • cat -e is not quite the same as echo -e.
    – muru
    Commented Jan 1, 2016 at 19:02

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.