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?

3
  • 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, 2021 at 7: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, 2021 at 7: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. May 20, 2021 at 17:17

3 Answers 3

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.

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/
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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .