📜 ⬆️ ⬇️

How to copy files and folders correctly, excluding some of them

The topic is written in response to similar .

The author of the original topic offers to solve the problem in the forehead - namely, copy all the files and then delete unnecessary ones. This may be a good solution if you, of course, do not need to copy your entire home folder to a USB flash drive, with the exception of your video collection.

But the main problem of this approach is different - it does not correspond to the unix ideology: complex tasks are solved by a combination of simple utilities.
')
Under the cat details about the methods of solving this class of problems - do not consider this as a ready-made recipe.


0. Decomposition


The solution of any complex task begins with parsing it into its component parts. So we need to copy some set of files by filtering it beforehand.
So - getting a list of files, filtering, copying.

1. Getting a list of files



Usually we review the file list with the ls program. Its output looks like this:
$ ls -1 dir1 dir2 file1.bin file2.txt 

Is there such a conclusion? No, because there is not enough information in it - we need to copy files recursively, which means it would be much more convenient for us if the first program in our chain produced the names of the files there along with the paths.

The next program that comes to mind is find
 $ find ./ ./ ./dir1 ./dir1/file7.txt ./dir2 ./file1.bin ./file2.txt 

Already better, but the directories were also included in the output, but we don’t need them. Let's try this:
 $ find ./ -type 'f' ./dir1/file7.txt ./file1.bin ./file2.txt 


Here is what you need there. List of files.

2. Filtering



This file list needs to be filtered. Redirect the output of our previous command to the grep program.
 $ find ./ -type 'f' | grep 2 ./dir2 ./file2.txt 


Good, but under the conditions of the task it is worth excluding the files, so a little change our pipeline
 $ find ./ -type 'f' | grep -v 2 ./dir1/file7.txt ./file1.bin 


The first two parts are completed.

3. Copying



From the man page for the cp command, we can find out that the source file needs to be passed to the cp program as an argument, but for now we can only redirect the list to standard input .
Let's use the xargs utility - it accepts standard input and calls the specified program with parameters from the standard input. So:
 $ find ./ -type 'f' | grep -v 2 | xargs -n 1 -I % cp --parents "%" /path/to/dest/dir/ 

-n 1 means that only one line from the standard input is inserted into the command, and -I% defines the character that will be replaced in the target command by the line from the standard input. In our case it will be
  cp --parents "./dir1/file7.txt" /path/to/dest/dir/ cp --parents "./file1.bin" /path/to/dest/dir/ 


We can assume that the problem is solved.

Instead of conclusion


I hope that this description will help to properly approach the solution of such simple as well as more complex tasks.

It should be noted that

Source: https://habr.com/ru/post/150830/


All Articles