Ubuntu – Argument list too long when copying files

command linefiles

I just asked a question related to how I can count the files of particular extension. Now I want to cp these files to a new dir.

I am trying,

cp *.prj ../prjshp/

and

cp * | grep '\.prj$' ../prjshp/

but they are giving the same error,

bash: /bin/cp: Argument list too long

How do I copy them?

Best Answer

cp *.prj ../prjshp/ is the right command, but you've hit a rare case where it runs into a size limitation. The second command you tried doesn't make any sense.

One method is to run cp on the files in chunks. The find command knows how to do this:

find -maxdepth 1 -name '*.prj' -exec mv -t ../prjshp {} +
  • find traverses the current directory and the directories below it recursively.
  • -maxdepth 1 means to stop at a depth of 1, i.e. don't recurse into subdirectories.
  • -name '*.prj' means to only act on the files whose name matches the specified pattern. Note the quotes around the pattern: it will be interpreted by the find command, not by the shell.
  • -exec … {} + means to execute the specified command for all the files. It invokes the command multiple times if necessary, taking care not to exceed the command line limit.
  • mv -t ../prjshp moves the specified files into ../prjshp. The -t option is used here because of a limitation of the find command: the found files (symbolized by {}) are passed as the last argument of the command, you can't add the destination after it.

Another method is to use rsync.

rsync -r --include='*.prj' --exclude='*' . ../prjshp
  • rsync -r … . ../prjshp copies the current directory into ../prjshp recursively.
  • --include='*.prj' --exclude='*' means to copy files matching *.prj and exclude everything else (including subdirectories, so .prj files in subdirectories won't be found).