3

I'm trying to make a simple script that copies all of my $HOME into another folder in $HOME called Backup/. This includes all hidden files and folders, and excludes Backup/ itself. What I have right now for the copying part is the following:

shopt -s dotglob

for file in $HOME/*
do
    cp -r $file $HOME/Backup/
done

Bash tells me that it cannot copy Backup/ into itself. However, when I check the contents of $HOME/Backup/ I see that $HOME/Backup/Backup/ exists.

The copy of Backup/ in itself is useless. How can I get bash to copy over all the folders except Backup/. I tried using extglob and using cp -r $HOME/!(Backup)/ but it didn't copy over the hidden files that I need.

Tunaki
  • 132,869
  • 46
  • 340
  • 423
Hugo
  • 2,186
  • 8
  • 28
  • 44

4 Answers4

3

try rsync. you can exclude file/directories .

this is a good reference

http://www.maclife.com/article/columns/terminal_101_using_rsync_locally 
Tharanga Abeyseela
  • 3,255
  • 4
  • 33
  • 45
2

Hugo,

A script like this is good, but you could try this:

cp -r * Backup/; cp -r .* Backup/;

Another tool used with backups is tar. This compresses your backup to save disk space.

Also note, the * does not cover . hidden files.

user2691041
  • 145
  • 1
  • I'm compressing the archive after everything is copied over into the backup directory. I have `shopt -s dotglob` so that the * covers hidden dot files. I just need a way to exclude that one directory from the whole thing because it's useless to have a copy of the directory used for the backup in the backup itself. – Hugo Dec 30 '13 at 03:06
1

I agree that using rsync would be a better solution, but there is an easy way to skip a directory in bash:

for file in "$HOME/"*
do
    [[ $file = $HOME/Backup ]] && continue
    cp -r "$file" "$HOME/Backup/"
done
chepner
  • 497,756
  • 71
  • 530
  • 681
  • I looked up the syntax for the test && continue line you gave me and it seemed like it should work, but bash still gave me the `cp: cannot copy a directory into itself` – Hugo Dec 30 '13 at 15:12
  • Try printing the value of `$file` prior to each `cp` command, to see exactly which argument to `cp` is causing the problem. – chepner Dec 30 '13 at 15:45
  • Printing `$file` shows me that it's not skipping `$HOME/Backup`. I've tried changing from double brackets to single brackets and making it a whole if statement `if [ "$file" != "$backupdir" ]; then echo "$file" cp -r "$file" $backupdir fi` It acts like it's not even evaluating the `if`. – Hugo Dec 30 '13 at 16:18
  • 1
    What is the exact value of `$backupdir`? Since this is a string comparison, both `$file` and `$backupdir` will need to be identical: same directory path, same trailing `/` (or lack of trailing `/`), etc. Two different strings that logically represent the same path will still compare as different. – chepner Dec 30 '13 at 16:42
  • Sorry I took so long to respond. That was the problem. I had $backupdir with a trailing `/`. Thank you. – Hugo Jan 01 '14 at 18:53
1

This doesn't answer your question directly (the other answers already did that), but try cp -ua when you want to use cp to make a backup. This recurses directories, copies rather than follows links, preserves permissions and only copies a file if it is newer than the copy at the destination.

Mzzl
  • 3,926
  • 28
  • 39