4 Add detailed explainations of what's happening
source | link

You could use a find ... -type f, with a bash for-loop. In the loop, a combination of mkdir -p and dirname would let you recreate the folder structure, before simply copying each file with cp.

#!/bin/bash

dirA="/NAS/data/dir1/"
dirB="/mnt/databackup/dir1/"
while read -r file
do
    relative="${file##"$dirA"}"
    newfile="$dirB$relative"
    echo mkdir -p "$(dirname "$file")"
    echo cp -at "$file" "$newfile"
done < <(find "$dirA" -type f -mtime -1)
  • read is a bash builtin. It is classically used with -r to avoid some edge-case problems. It reads one line (at a time) from it's stdin. Here it, that stdin is the output of findfind.
  • ${var##string-to-remove} is a form of (advanced) bash substitutionparameter substitution
  • newfile="$dirB$relative". This is a classical bash concatenation
  • $(). This bash construct is called command substitution
  • mkdir -p create a directory and all it's ancestors as needed
  • cmd < file this is a classicalclassic redirection
  • <(cmd) this is called process substitutionprocess substitution. It substitute a filename as handle to the stdin [>()] or stdout [<()] of a command.

You can use explainshell.com to get more detailed explanations.

You could use a find ... -type f, with bash for-loop. In the loop, a combination of mkdir -p and dirname would let you recreate the folder structure, before simply copying each file with cp.

#!/bin/bash

dirA="/NAS/data/dir1/"
dirB="/mnt/databackup/dir1/"
while read -r file
do
    relative="${file##"$dirA"}"
    newfile="$dirB$relative"
    echo mkdir -p "$(dirname "$file")"
    echo cp -at "$file" "$newfile"
done < <(find "$dirA" -type f -mtime -1)
  • read is a bash builtin. It is classically used with -r to avoid some edge-case problems. It reads one line from it's stdin. Here it that stdin is the output of find.
  • ${var##string-to-remove} is a form of (advanced) bash substitution
  • newfile="$dirB$relative". This is a classical bash concatenation
  • mkdir -p create a directory and all it's ancestors as needed
  • cmd < file this is a classical redirection
  • <(cmd) this is called process substitution. It substitute a filename as handle to the stdin [>()] or stdout [<()] of a command.

You could use find ... -type f, with a bash for-loop. In the loop, a combination of mkdir -p and dirname would let you recreate the folder structure, before simply copying each file with cp.

#!/bin/bash

dirA="/NAS/data/dir1/"
dirB="/mnt/databackup/dir1/"
while read -r file
do
    relative="${file##"$dirA"}"
    newfile="$dirB$relative"
    echo mkdir -p "$(dirname "$file")"
    echo cp -at "$file" "$newfile"
done < <(find "$dirA" -type f -mtime -1)
  • read is a bash builtin. It is classically used with -r to avoid some edge-case problems. It reads one line (at a time) from it's stdin. Here, that stdin is the output of find.
  • ${var##string-to-remove} is a form of parameter substitution
  • newfile="$dirB$relative". This is a classical bash concatenation
  • $(). This bash construct is called command substitution
  • mkdir -p create a directory and all it's ancestors as needed
  • cmd < file this is a classic redirection
  • <(cmd) this is called process substitution. It substitute a filename as handle to the stdin [>()] or stdout [<()] of a command.

You can use explainshell.com to get more detailed explanations.

3 Add detail explainations of what's happening
source | link

You could use a find ... -type f, with bash for-loop. In the loop, a combination of mkdir -p and dirname would let you recreate the folder structure, before simply copying each file with cp.

#!/bin/bash

dirA="/NAS/data/dir1/"
dirB="/mnt/databackup/dir1/"
while read -r file
do
    relative="${file##"$dirA"}"
    newfile="$dirB$relative"
    echo mkdir -p "$(dirname "$file")"
    echo cp -at "$file" "$newfile"
done < <(find "$dirA" -type f -mtime -1)
  • read is a bash builtin. It is classically used with -r to avoid some edge-case problems. It reads one line from it's stdin. Here it that stdin is the output of find.
  • ${var##string-to-remove} is a form of (advanced) bash substitution
  • newfile="$dirB$relative". This is a classical bash concatenation
  • mkdir -p create a directory and all it's ancestors as needed
  • cmd < file this is a classical redirection
  • <(cmd) this is called process substitution. It substitute a filename as handle to the stdin [>()] or stdout [<()] of a command.

You could use a bash for-loop.

#!/bin/bash

dirA="/NAS/data/dir1/"
dirB="/mnt/databackup/dir1/"
while read -r file
do
    relative="${file##"$dirA"}"
    newfile="$dirB$relative"
    echo mkdir -p "$(dirname "$file")"
    echo cp -at "$file" "$newfile"
done < <(find "$dirA" -type f -mtime -1)

You could use a find ... -type f, with bash for-loop. In the loop, a combination of mkdir -p and dirname would let you recreate the folder structure, before simply copying each file with cp.

#!/bin/bash

dirA="/NAS/data/dir1/"
dirB="/mnt/databackup/dir1/"
while read -r file
do
    relative="${file##"$dirA"}"
    newfile="$dirB$relative"
    echo mkdir -p "$(dirname "$file")"
    echo cp -at "$file" "$newfile"
done < <(find "$dirA" -type f -mtime -1)
  • read is a bash builtin. It is classically used with -r to avoid some edge-case problems. It reads one line from it's stdin. Here it that stdin is the output of find.
  • ${var##string-to-remove} is a form of (advanced) bash substitution
  • newfile="$dirB$relative". This is a classical bash concatenation
  • mkdir -p create a directory and all it's ancestors as needed
  • cmd < file this is a classical redirection
  • <(cmd) this is called process substitution. It substitute a filename as handle to the stdin [>()] or stdout [<()] of a command.
2 fix the loop
source | link

You could use a bash for-loop.

#!/bin/bash

dirA="/NAS/data/dir1/"
dirB="/mnt/databackup/dir1/"
for file in find "$dirA" -typewhile fread -mtimer -1file
do
    relative="${file##"$dirA"}"
    newfile="$dirB$relative"
    echo mkdir -p "$(dirname "$file")"
    echo cp -at "$file" "$newfile"
done < <(find "$dirA" -type f -mtime -1)

You could use a bash for-loop.

#!/bin/bash

dirA="/NAS/data/dir1/"
dirB="/mnt/databackup/dir1/"
for file in find "$dirA" -type f -mtime -1
do
    relative="${file##"$dirA"}"
    newfile="$dirB$relative"
    echo mkdir -p "$(dirname "$file")"
    echo cp -at "$file" "$newfile"
done

You could use a bash for-loop.

#!/bin/bash

dirA="/NAS/data/dir1/"
dirB="/mnt/databackup/dir1/"
while read -r file
do
    relative="${file##"$dirA"}"
    newfile="$dirB$relative"
    echo mkdir -p "$(dirname "$file")"
    echo cp -at "$file" "$newfile"
done < <(find "$dirA" -type f -mtime -1)
1
source | link