Copy files from a directory to a sub-directory (excluding the sub-directory itself)

12,721

Solution 1

Assuming you are using bash as your interactive shell, you can enable extglob which allows you to specify "all files except these ones".

shopt -s extglob
cd Parent
cp !(Child1) Child1/

Solution 2

Three excellent answers that demonstrate the flexibility of linux. And it's always a good idea to be familiar with basic command line operations. Personally I prefer a hybrid approach and I try using mc (midnight commander) when it's available.

sudo apt-get install mc

will get it for you. Surviving tyrannosaurs like me might notice the resemblance with Norton commander from the DOS days. Its operation is quite intuitive. You have two panels. You switch between them with TAB. There are Fn key shortcuts for basic operations, like view, edit, copy, move, rename, delete, etc.

mc

In your case, all you have to do is type mc in your terminal window and navigate to Parent folder in one panel, child folder on the other. Then select parent panel and press + and then enter. This will select all files and folders in the panel. With arrow keys go on top of Child1 folder and press Ins key. This will de-select that folder (Ins key toggles select status of an item.) Now press F5 and all selected content will be copied to the other panel (which is inside Child1 folder.)

I am providing this information only for the sake of completeness and to further demonstrate the variety of solutions available. By all means, go on and learn the basic linux commands and their variations. You can always rely on them being available at your fingertip on any system.

Solution 3

Less elegant than extglob, but also works...

mkdir -p Child1; for i in ./*; do [[ "$i" != ./Child1 ]] && echo cp -vr "$i" Child; done
cp -vr ./file1 Child1
cp -vr ./file100 Child1
cp -vr ./Folder2 Child1
cp -vr ./Folder3 Child1

Remove echo after testing to actually move the files. If you have hidden files and want to include them, first run shopt -s dotglob.

As a script (again, you need to remove echo to actually move files):

#!/bin/bash

mkdir -p Child1                    # create Child1 if it does not exist
for i in ./*; do                   # act on all the files in the current directory 
   [[ "$i" != ./Child1 ]] &&       # if the file is not Child1 itself
   echo cp -vr "$i" Child1         # move the file into Child1
done

Solution 4

rsync has an option to exclude files or directories using --exclude option.

So in this case I think rsync would be a nice choice.

mkdir -p Child1; rsync -av --progress ./* Child1 --exclude Child1

Solution 5

Try :

cd [WhereeverParentLies]
cp ./* ./Child1/

There will be a message that cp omitted the "Child1" directory.

Share:
12,721

Related videos on Youtube

tHe_VaGaBonD
Author by

tHe_VaGaBonD

Kunal's (definitely) not Unix @kunalkrishna85

Updated on September 18, 2022

Comments

  • tHe_VaGaBonD
    tHe_VaGaBonD over 1 year

    I have created a folder (directory) named Parent which contains several files (namely file1 file2 ... file100) and subdirectories (Folder2, Folder3 etc) and a particular sub-directory named Child1 which itself may contain files and folders. Now, I want to copy all the contents of Parent excluding Child1 into the folder Child1.

    The final content of 'Child1' should be something like this:

     Old content of Child1
     file1 ... file100 + Folder2 Folder3 + etc.
    

    How can I achieve this?

  • geirha
    geirha about 11 years
    find | xargs is bad practice. It'll fail for filenames containing whitespace or quote characters. Using the -exec action of find is the preferred, and fully safe, way.
  • llt
    llt about 11 years
    thanks for letting me know. I haven't encountered that yet so I didn't know it could be a problem. so would the command be find Parent/ -maxdepth 1 -type f -exec cp -t Parent/Child?
  • tHe_VaGaBonD
    tHe_VaGaBonD about 11 years
    your explanation was indeed good. But, I just started learning Shell Scripting and while learning cp command this question hit me. So, wanted to achieve through BASIC commands without the help of other packages.
  • Manuel
    Manuel about 11 years
    Yes, it only copies files. This is not a general solution, but in the problem only the copying of files was mentioned.
  • tHe_VaGaBonD
    tHe_VaGaBonD about 11 years
    @Manuek : but it also omitted 'Child2' and 'Child3' which are other directories present in Parent. So your suggestion just copies FILES and no FOLDER from Parent to Child1. However,I achieved that with cp -R ./* ./Child1/ with warning message : cp: cannot copy a directory, ‘./child1’, into itself, ‘./child1/child1’ which is obviously expected.
  • tHe_VaGaBonD
    tHe_VaGaBonD about 11 years
    @Manuek : thanx, I edited the question. However question statement > Now, I want to copy all the contents of 'Parent' excluding the > 'Child1' into the folder 'Child1'. should have conveyed that ,I wanted to copy the folders too.
  • Manuel
    Manuel about 11 years
    Ok, then it depends on the folders... If the number is low, i would manually cp -r them
  • goo
    goo over 6 years
    @geirha find (and xargs, du, grep, egrep, fgrep, rgrep, perl, shuf, 'sort, uniq, xz, unxz, xzcat, lzma, unlzma, lzcat` and modinfo) have command line switches for dealing with filenames separated by NUL chars (filenames may contain any character EXCEPT NUL or //). See the man pages.
  • Zanna
    Zanna over 6 years
  • geirha
    geirha over 6 years
    @waltinator, yes, GNU extends the standard commands find and xargs, among others, with the ability to write and read NUL delimited data, so adding the -print0 action for the find, and -0 option for the xargs would also make it safe.