0

I'm new to Linux, I am trying to write a Bash script which will copy a directory's content to a backup folder which will be created, without using the -r switch. I assumed that the max depth of the directory is 2 . I placed in some echo's at the script and I have noticed that the for loop takes the first and only argument to be the path of the current folder - it absolutely ignores all files in the directory. I tried changing the code a few times with no success. Is there a syntax error? Is the logic not right? I would love to get an answer. Thanks alot!

pwd > route
r=$(<route)
cd ..
if [ ! -d backup ]; then
    mkdir backup
fi
cd backup
pwd > buroute
BUrout=$(<buroute)
cd "$r"
for i in $r; do
    if [ -f $i ]; then
        cp $i "$BUrout"
    fi
    if [ -d $i ]; then
        if [ $i == $r ]; then
            continue
        fi
        cd "$i"
        pwd > current
        cur=$(<current)'/'
        for file in "$cur"; do
            if [ -f "$file" ]; then
                cp $file "$BUrout"
            fi
        done
        cd ..
    fi
done
RanAB
  • 103

1 Answers1

2

I don't quite see why you can't just use cp -r or rsync -a for this, unless you explicitly want to flatten the directory structure, but never mind.

You're doing a lot to get the path to subdirectories: cd into the directory, pwd to a file and then read that file into a variable. Instead you could just use e.g. BUrout="$PWD/backup" ($PWD holds the pathname of the current working directory).

You will never process any files because your loop is over the name of a directory. What you want is probably for i in "$r"/*; do, and similarly in the second loop.

Always double quote your variable expansions! E.g. if [ "$i" = "$r" ] (note also single =, not double). See both "Why does my shell script choke on whitespace or other special characters?" and "Security implications of forgetting to quote a variable in bash/POSIX shells"

Your script should not need a single cd. Scripts that steps into and out of directories are really hard to debug.

Apart from that, no syntax errors, and the logic seems to be correct.

May I suggest something like this, which is still using the same looping logic and mostly the same tests as your code is using, but without the calls to cd and without having to fiddle too much with directory names:

#!/bin/sh

source="$1"
dest="$2"

mkdir -p "$dest"  # creates destination directory if not already exists

for name in "$source"/*; do
    if [ -f "$name" ]; then
        cp "$name" "$dest"
    elif [ -d "$name" ]; then
        for name2 in "$name"/*; do
            if [ -f "$name2" ]; then
                cp "$name2" "$dest"
            fi
        done
    fi
done

Or, using shortcut-syntax which seems to appeal to some people:

#!/bin/sh

source="$1"
dest="$2"

mkdir -p "$dest"  # creates destination directory if not already exists

for name in "$source"/*; do
    [   -f "$name" ] && { cp "$name" "$dest"; continue; }
    [ ! -d "$name" ] && continue
    for name2 in "$name"/*; do
        [ -f "$name2" ] && cp "$name2" "$dest"
    done
done

This script takes two arguments, the source directory and the target/destination directory:

$ ./script mydir some_new_backup_dir

No attempt is made to check whether any of the cp commands would overwrite an existing file in the target directory.

Note also that both of these scripts are /bin/sh script. They uses no things that are specific to the bash shell.


Assuming that the target directory exists, this is more or less equivalent to

find source_dir -maxdepth 2 -type f -exec cp {} target_dir ';'
Kusalananda
  • 333,661