Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I want to copy a folder to another location, while excluding some specific files

Here is my current script:

#!/bin/bash

if [ -n "$2" ]
then
    source=$(readlink -f $1)
    destination=$(readlink -f $2)
else
    printf "\nProper syntax: my_copy source_folder destination_folder\n"
        exit
fi


params=(
    --exclude='.git'
    --exclude='deploy'
    --exclude='app/config/database.php'
    --exclude='app/config/config.php'
)


cd $source
rsync " -a ${params[@]} $source/* $destination"

When I run my script, I get this error:

rsync: link_stat "-a --exclude=.git" failed: No such file or directory (2)
rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1070) [sender=3.0.9]

What am I doing wrong?

share|improve this question
    
rsync -a "${params[@]}" $source/ $destination if not work then try echo rsync -a "${params[@]}" $source/ $destination| sh –  Rahul Patil Sep 10 '13 at 11:30
add comment

2 Answers 2

up vote 2 down vote accepted

To see what's happening change the rsync command to an echo command first.

$ echo "rsync \" -a ${params[@]} $source/* $destination\""

Potential Fixes

I would change that line to this instead:

$ rsync -a "${params[@]}" "$source/"* "$destination"
share|improve this answer
    
why multi source and destination there ? –  Rahul Patil Sep 10 '13 at 11:33
    
@RahulPatil - not following your question –  slm Sep 10 '13 at 11:39
1  
@Loupax - get rid of the double quotes around the arguments. I think that was the original issue. See update. You can try it with and without the $(echo ...) –  slm Sep 10 '13 at 12:00
1  
First script, feels good :) –  Loupax Sep 10 '13 at 12:09
1  
@Loupax - good looking first script. Good use of arrays, thinking the right way! –  slm Sep 10 '13 at 12:15
show 4 more comments

If you'd written this:

rsync " -a $params $source/* $destination"

then the rsync command would be getting a single string as its argument, because all the variables are expanded inside double quotes. For example, if $params is --exclude=.git, $source is /somewhere and $destination is /elsewhere then the argument would be

 -a --exclude=.git /somewhere/* /elsewhere

There's an added wrinkle: "${params[@]}" splits the array into separate parameters. The text before ${params[@]} is attached to the first array element and the text after ${params[@]} is attached to the last array element. So rsync is called with four parameters:

 -a --exclude=.git
--exclude=deploy
--exclude=app/config/database.php
--exclude=app/config/config.php /somewhere/* /elsewhere

Each parameter must be a separate double-quoted string. You need the double quotes to protect the expansion of the variables in case they contain whitespace or wildcard characters. For the array expanded with ${NAME[@]}, "${NAME[@]}" places each element in a separate parameter. The spaces that separate elements, and the characters that are intended to function as wildcards, must remain unquoted.

rsync -a "${params[@]}" -- "$source"/* "$destination"

This excludes dot files directly under $source, because of the /. To copy files under $source to files with the same name under $destination, just put a slash after the path to the source directory.

rsync -a "${params[@]}" -- "$source/" "$destination"
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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