2

Under /home folder we have many subfolders, as the following:

/home/user1
/home/user2/user_sub_2
/home/user3/user_sub_3/info_sub
/home/user4/INFO_FOLDER

We want to copy all the files under /home, recursively, to the /tmp/calculation folder. All files should be placed directly into the target folder (no subdirectories should be created). If two or more files have the same name, then the most recently modified file should be copied to /tmp/calculation.

What is the right approach to do this action?

Kusalananda
  • 333,661
yael
  • 13,106

2 Answers2

5
find /home ! -type d -exec bash -c '
    for pathname do
        if [ "$pathname" -nt "/tmp/calculation/${pathname##*/}" ]
        then
            cp "$pathname" /tmp/calculation
        fi
    done' bash {} +

This would find all non-directory files under /home, and for batches of these it would call a short bash script.

The short bash script would loop over the current batch of pathnames, and for each would test with the -nt test whether current file is newer than the copy in the target directory (or whether a copy does not exist there). If the file in the target directory is older or if it does not exist, cp is used to copy the current file to the target directory.

The parameter expansion ${pathname##*/} would remove any directory path before the actual filename, leaving only the filename portion of the pathname. It could be replaced by $(basename "$pathname").

Related:


Mostly unrelated:

The -nt test is a non-standard test. This is why I chose to use bash for the internal script that find calls. Using sh -c instead of bash -c would probably have worked, but the semantics of the test may differ slightly between shell that may masquerade as sh.

For example, in the bash, zsh and ksh shells, the -nt test is true if the first operand has a modification timestamp that in newer than that of the second operand, or if the second operand does not exist.

In the dash shell, however, both files most exist and the first file has to be newer than the second for the test to be true (according to the documentation). This difference would not have been an issue in this case.

In the yash shell it's not specified in the manual what happens if either file does not exist.

It is therefore safest to use a specific shell when using a non-standard facility, even if it, in this specific case, would probably have worked with sh -c anyway.

(The downside with using bash in this instance is that it only has a one second resolution in the timestamps that it compares, but that's another story)

Kusalananda
  • 333,661
  • why you use - -type d , this searched only folders – yael Feb 25 '19 at 20:58
  • @yael I used ! -type d not -type d. I did this because you never said anything about what types of files you wanted to copy, so instead of -type f I used ! -type d to copy any type of non-directory file. – Kusalananda Feb 25 '19 at 21:00
  • ok , lets say - /tmp/calculation folder is empty folder , in that case can you add the right syntax for this case? – yael Feb 25 '19 at 21:02
  • @yael I don't understand what you mean by your last comment. If the folder is empty, it should copy files there. Does it not do that for you? – Kusalananda Feb 25 '19 at 21:04
0

I tried with below command and it worked fine

for file in `find /home -type f | awk -F "/" '{print $NF}'`
do
    for dir in `find . -type d| sed "s/\.//g"| sed 's/$/\//g'`
    do
        sudo find $dir -type f -iname $file | awk '{print "ls -ltrh" " " $0}'
    done | sh | sed -n '$p'
done | awk '{print "cp -rvfp" " " $NF " " "/destinationlocationtocopy/"}' | sh
Kusalananda
  • 333,661