I am already using below command to copy files from a specific date.

Previously I used this command and it worked well but now it was showing an error:

-bash: /bin/cp: Argument list too long

Commends used:

cd /share/new/
cp `find . -type f -newermt '16 july 2018'` /share/test

I need to copy all files in the folder "new" from July 20th to today date. How can I achieve this?

up vote 9 down vote accepted

Don't use cp directly with the output of find.

It might passes way many too files in a single step (and that's why you get the error Argument list too long).

Use the -exec parameter of find, which execute the given command passing a every matched file to cp, one at a time:

cd /share/new/
find . -type f -newermt '16 july 2018' -exec cp {} /share/test \;
  • 1
    its working :: "" find . -type f -newermt '16 july 2018' -exec cp {} /share/test/ \; "" missing "/" after test because test is a directory – Venki Sep 25 at 9:26
  • 1
    I added quotes to the "{}". This will make sure files with names containing spaces are handled correctly. – vanadium Sep 25 at 10:22
  • 4
    @vanadium find's -exec executes the program directly. It doesn't invoke a shell; {} is replaced with the filename as a single argument regardless of quoting (which find never actually sees, anyway). – Ian Emnace Sep 25 at 17:51
  • 3
    You can improve the efficiency of this command (which probably matters if OP is getting "argument list too long") by specifying the destination explicitly with the -t switch, rather than by syntax, and making use of + which constructs an argument list, ie find <tests> -exec cp -t /share/test {} + The argument list is broken as many times as needed to complete without exceeding the limit. This avoids launching cp n times where n is the number of files... – Zanna Sep 25 at 17:58
  • 1
    @IanEmnace Thank! Removed the quotes again, not needed indeed! – vanadium Sep 25 at 18:36

use find -exec:

find /share/new/ -type f -newermt '16 july 2018' -exec cp {} /share/test \;
  • getting same error for your command also find: missing argument to `-exec' – Venki Sep 25 at 9:18
  • I think your missing the \; at the end. – RoVo Sep 25 at 9:20
  • test is a directory i am missing / after test – Venki Sep 25 at 9:31

Make use of the -exec action of find and the -t option of cp; I also recommend the -i or -n options if you don’t want to overwrite identically named files by accident:

find ... -exec cp -i -t TARGET -- {} +

The other current answers spawn a cp child process for every matching file while this answer only spawns as many as necessary based on the total program argument length limit (see below) which will make a big difference once you reach a couple of thousand matches which appears to be your case.


From the find(1) manual:

  • -exec command ; – Execute command […]. All following arguments to find are taken to be arguments to the command until an argument consisting of ; is encountered. The string {} is replaced by the current file name being processed everywhere it occurs in the arguments to the command […]. The specified command is run once for each matched file. […]

  • -exec command {} + – This variant of the -exec action runs the specified command on the selected files, but the command line is built by appending each selected file name at the end; the total number of invocations of the command will be much less than the number of matched files. […]

From the cp(1) manual:

  • -t, --target-directory=DIRECTORY – copy all SOURCE arguments into DIRECTORY
  • -i, --interactive – prompt before overwrite
  • -n, --no-clobber – do not overwrite an existing file

You should try this syntax:

find /share/new/ -type f -newermt '16 july 2018' -exec cp -R /share/test/ {} \;
  • 2
    What is the purpose of the -R here? Doesn't it recursively copy /share/test to all the files found? That seems wrong. – PerlDuck Sep 25 at 18:12
  • Well, no. The OP wants to copy a $source_file to a $target_directory. The command you propose instead recursively copies the $target_directory to the $source_file. This doesn't make sense. Not only the direction is just the other way round, but also when copying recursively, the target must be a directory, not a file. When we run cp -R /source/directory /target/file then we get cp: cannot overwrite non-directory 'target/file' with directory '/source/directory'. – PerlDuck Sep 26 at 8:33

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.