2

I have a directory structure as below:

source-dir---
            |----- file-1
            |----- file-2
            |----- file-3
            |----- folder-1
                      |---- file-4
                      |---- file-5

I want to copy all the files from the source directory to destination directory and maintain the same folder structure but I want to avoid copying the file-5 from its sub-directory.

Expecting the destination directory to be as follow:

destination-dir---
                 |----- file-1
                 |----- file-2
                 |----- file-3
                 |----- folder-1
                           |---- file-4

Is it possible to achieve above behaviour using cp command itself? or rsync or any specific regex using find command?

αғsнιη
  • 41,407
Ankit Raj
  • 173
  • Does the filename file-5 only occur in folder-1, or can a file of the same name appear in other parts of the directory tree as well? – AdminBee May 20 '21 at 07:32
  • @AdminBee the file-5 only occur in folder-1 and is unique, I was trying this rsync command but it was not working. rsync -a --exclude={'file-5', '/source-dir/folder-1/'} ~/source/ ~/destination/, Other way is if I execute single line bash : cp -r ~/source/ ~/destination/; rm ~/destination/folder-1/file-5, Do you have any better suggestion or solution? – Ankit Raj May 20 '21 at 07:47
  • 2
    since I saw you never have accepted any answer you received on your question (Stackexchange networks wide), please consider to a read this page What does it mean when an answer is "accepted"? about how to accept an answer and what accepting an answer means. – αғsнιη May 20 '21 at 17:17

3 Answers3

3

This should work, excluding only file-5 from copying in any level of sub-directories of the source directory but not if it exist in the top level:

cd /path/to/source
find . ! -path './*/file-5' -type d,f -exec sh -c '
    [ -d "$1" ] && echo mkdir -vp "/path/to/dest/$1" || echo cp -v "$1" "/path/to/dest/$1"
' sh_cp {} \;

if you only want to exclude that specifc file from a specifc subdirectory, strictly mention that instead, like ./folder-1/file-5 to exclude only this file and from that directory only.

remove echo in front of the mkdir and cp commands if you were happy with dry-run result.

αғsнιη
  • 41,407
2

If I understand you correctly, you wanted to skip copying a specific file (file-5) from a specific directory (folder-1) then you can instruct rsync to exclude the said file as follows:

$ rsync -avz -f'- folder-1/file-5' ~/source/ ~/destination/
guest_7
  • 5,728
  • 1
  • 7
  • 13
1

This question make me thinks to bash globbing

This is a little script with explanation comment:

#!/bin/bash

Check that the arguments are two.

Source and destination

[ ${#@} -eq 2 ] || exit 1

Remove, a possible, traling backslash

src="${1%/}" dst="${2%/}"

Enalble needed option for gloobin

shopt -q extglob || shopt -s extglob shopt -q globstar || shopt -s globstar

Set here the name to ignore

GLOBIGNORE="$src"/*/file-5

for e in "$src"/**; do # Skip the base directory [ "$e" != "$src/" ] || continue

# If we process a directory then create it
# in the destionation
[ -d "$e" ] && echo mkdir "$dst/$e" && continue

# Plain file, do then copy
[ -f "$e" ] && echo cp "$e" "$dst/"

done

Rename the script, eg: sample.sh, then call as sample.sh src_path dst_path

Remove the echo when happy. Of course you can set the GLOBIGNORE to whatever you need to skip.