Argument list too long when copying files Announcing the arrival of Valued Associate #679:...

Sentence with dass with three Verbs (One modal and two connected with zu)

Why are my pictures showing a dark band on one edge?

Is there hard evidence that the grant peer review system performs significantly better than random?

Is CEO the "profession" with the most psychopaths?

Deconstruction is ambiguous

Crossing US/Canada Border for less than 24 hours

What does it mean that physics no longer uses mechanical models to describe phenomena?

Converted a Scalar function to a TVF function for parallel execution-Still running in Serial mode

How could we fake a moon landing now?

1-probability to calculate two events in a row

Drawing spherical mirrors

Trademark violation for app?

One-one communication

What is an "asse" in Elizabethan English?

How to identify unknown coordinate type and convert to lat/lon?

Central Vacuuming: Is it worth it, and how does it compare to normal vacuuming?

What would you call this weird metallic apparatus that allows you to lift people?

Significance of Cersei's obsession with elephants?

AppleTVs create a chatty alternate WiFi network

How long can equipment go unused before powering up runs the risk of damage?

An adverb for when you're not exaggerating

Why do early math courses focus on the cross sections of a cone and not on other 3D objects?

How many time has Arya actually used Needle?

How does the math work when buying airline miles?



Argument list too long when copying files



Announcing the arrival of Valued Associate #679: Cesar Manara
Planned maintenance scheduled April 23, 2019 at 23:30UTC (7:30pm US/Eastern)Deleting many files results in “argument list too long”“-bash: /usr/bin/rename: Argument list too long”need to copy images from 1000 subfolders into one single folderWhat's the difference between <<, <<< and < < in bash?List files of particular extensionWhat is the fastest way in terminal to get a count of files when there is so many of them?How can I unzip files with “weird” extensions in ubuntu?Differences between /bin, /sbin, /usr/bin, /usr/sbin, /usr/local/bin, /usr/local/sbinShell script errors?How do I move thousands of files from a list?Argument list too long errorA general purpose way to rename all the files in a directoryHow can I count files with a particular extension, and the directories they are in?Deleting many files results in “argument list too long”How to list and remove files only if multiple conditions are metHow to copy file from a list to a new folder?





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom:0;
}







21















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?










share|improve this question

























  • Related: Does "argument list too long" restriction apply to shell builtins?

    – codeforester
    Nov 22 '17 at 21:19


















21















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?










share|improve this question

























  • Related: Does "argument list too long" restriction apply to shell builtins?

    – codeforester
    Nov 22 '17 at 21:19














21












21








21


6






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?










share|improve this question
















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?







command-line files






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Apr 13 '17 at 12:23









Community

1




1










asked Nov 15 '12 at 21:16









Sam007Sam007

1,38391826




1,38391826













  • Related: Does "argument list too long" restriction apply to shell builtins?

    – codeforester
    Nov 22 '17 at 21:19



















  • Related: Does "argument list too long" restriction apply to shell builtins?

    – codeforester
    Nov 22 '17 at 21:19

















Related: Does "argument list too long" restriction apply to shell builtins?

– codeforester
Nov 22 '17 at 21:19





Related: Does "argument list too long" restriction apply to shell builtins?

– codeforester
Nov 22 '17 at 21:19










4 Answers
4






active

oldest

votes


















28














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).






share|improve this answer



















  • 2





    rsync, by far the easiest solution here.

    – ntk4
    Jul 18 '17 at 17:05











  • To be somewhat nitpicky, the second command cp * | grep '.prj$' ../prjshp/ does not make any sense, but can be a syntactically valid, if * expands to list of files with the last one being a directory ( aka cp SOURCE1 SOURCE2....DEST ). The pipe does not make any sense, sure, but also remains syntactically valid as far as shell is concerned - it will dup() the file descriptors just fine, it's just that reader end of the pipe won't get any data because cp doesn't write any.

    – Sergiy Kolodyazhnyy
    Feb 4 at 0:48



















13














This command copies the files one by one and will work even if there are too many of them for * to expand into a single cp command:



for i in *; do cp "$i" ../prjshp/; done





share|improve this answer


























  • This works for me.

    – 1rq3fea324wre
    Nov 15 '17 at 18:38






  • 1





    Simple and effective. I had a similar issue removing ~1/4 million jpegs I had extracted from a video for a project. This is the approach I used.

    – Elder Geek
    Nov 26 '17 at 16:17



















3














There's 3 key points to keep in mind when facing Argument list too long error:




  • The length of command-line arguments is limited by ARG_MAX variable, which by POSIX definition is "...[m]aximum length of argument to the exec functions including environment data" (emphasis added)". That is, when shell executes a non-built-it command, it has to call one of exec() to spawn that command's process, and that's where ARG_MAX comes into play. Additionally, the name or path to the command itself ( for example, /bin/echo ) plays a role.


  • Shell built-in commands are executed by shell, which means the shell doesn't use exec() family of functions and therefore aren't affected by ARG_MAX variable.


  • Certain commands, such as xargs and find are aware of ARG_MAX variable and repeatedly perform actions under that limit



From the points above and as shown in Kusalananda's excellent answer on related question, the Argument list too long can also occur when environment is big. So taking in consideration that each user's environment may vary, and the argument size in bytes is relevant, it's hard to come up with a single number of files/arguments.



How to handle such error ?



The key thing is to focus not on the number of files, but focus on whether or not the command you're going to use involves exec() family of function and tangentially - the stack space.



Use shell built-ins



As discussed before, the shell built-ins are immune to ARG_MAX limit, that is things such as for loop, while loop, built-in echo, and built-in printf - all those will perform well enough.



for i in /path/to/dir/*; do cp "$i" /path/to/other/dir/; done


On related question about deleting files, there was a solution as such:



printf '%s' *.jpg | xargs -0 rm --


Note that this uses shell's built-in printf. If we're calling the external printf, that will involve exec(), hence will fail with large number of arguments:



$ /usr/bin/printf "%s" {1..7000000}> /dev/null
bash: /usr/bin/printf: Argument list too long


bash arrays



According to an answer by jlliagre, bash doesn't impose limits on arrays, so building array of filenames and using slices per iteration of loop can be done as well, as shown in danjpreron's answer:



files=( /path/to/old_dir/*.prj )
for((I=0;I<${#files[*]};I+=1000)); do
cp -t /path/to/new_dir/ "${files[@]:I:1000}"
done


This, however, has limitation of being bash-specific and non-POSIX.



Increase stack space



Sometimes you can see people suggest increasing the stack space with ulimit -s <NUM>; on Linux ARG_MAX value is 1/4th of stack space for each program, which means increasing stack space proportionally increases space for arguments.



# getconf reports value in bytes, ulimit -s in kilobytes
$ getconf ARG_MAX
2097152
$ echo $(( $(getconf ARG_MAX)*4 ))
8388608
$ printf "%dKn" $(ulimit -s) | numfmt --from=iec --to=none
8388608
# Increasing stack space results in increated ARG_MAX value
$ ulimit -s 16384
$ getconf ARG_MAX
4194304


According to answer by Franck Dernoncourt, which cites Linux Journal,
one can also recompile Linux kernel with larger value for maximum memory pages for arguments, however, that's more work than necessary and opens potential for exploits as stated in the cited Linux Journal article.



Avoid shell



Another way, is to use python or python3 which come by default with Ubuntu. The python + here-doc example below, is something I personally used to copy a large directory of files somewhere in the range of 40,000 items:



$ python <<EOF
> import shutil
> import os
> for f in os.listdir('.'):
> if os.path.isfile(f):
> shutil.copy(f,'./newdir/')
> EOF


For recursive traversals, you can use os.walk.



See also:




  • What defines the maximum size for a command single argument?






share|improve this answer

































    2














    IMHO, the optimal tools for dealing with hordes of files are find and xargs. See man find. See man xargs. find, with its -print0 switch, produces a NUL-separated list of filenames (filenames may contain any character execpt NUL or /) that xargs understands, using the -0 switch. xargs then builds the longest command allowed (the most filenames, no half-filename at the end) and executes it. xargs repeats this until find supplies no more filenames. Run xargs --show-limits </dev/null to see the limits.



    To solve your problem, (and after checking man cp to find --target-directory=):



    find . -maxdepth 1 -type f -name '*.prj' -print0 | xargs -0 cp --target-directory=../prjshp/





    share|improve this answer
























      Your Answer








      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "89"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2faskubuntu.com%2fquestions%2f217764%2fargument-list-too-long-when-copying-files%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      28














      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).






      share|improve this answer



















      • 2





        rsync, by far the easiest solution here.

        – ntk4
        Jul 18 '17 at 17:05











      • To be somewhat nitpicky, the second command cp * | grep '.prj$' ../prjshp/ does not make any sense, but can be a syntactically valid, if * expands to list of files with the last one being a directory ( aka cp SOURCE1 SOURCE2....DEST ). The pipe does not make any sense, sure, but also remains syntactically valid as far as shell is concerned - it will dup() the file descriptors just fine, it's just that reader end of the pipe won't get any data because cp doesn't write any.

        – Sergiy Kolodyazhnyy
        Feb 4 at 0:48
















      28














      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).






      share|improve this answer



















      • 2





        rsync, by far the easiest solution here.

        – ntk4
        Jul 18 '17 at 17:05











      • To be somewhat nitpicky, the second command cp * | grep '.prj$' ../prjshp/ does not make any sense, but can be a syntactically valid, if * expands to list of files with the last one being a directory ( aka cp SOURCE1 SOURCE2....DEST ). The pipe does not make any sense, sure, but also remains syntactically valid as far as shell is concerned - it will dup() the file descriptors just fine, it's just that reader end of the pipe won't get any data because cp doesn't write any.

        – Sergiy Kolodyazhnyy
        Feb 4 at 0:48














      28












      28








      28







      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).






      share|improve this 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).







      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered Nov 15 '12 at 21:31









      GillesGilles

      45.6k13102142




      45.6k13102142








      • 2





        rsync, by far the easiest solution here.

        – ntk4
        Jul 18 '17 at 17:05











      • To be somewhat nitpicky, the second command cp * | grep '.prj$' ../prjshp/ does not make any sense, but can be a syntactically valid, if * expands to list of files with the last one being a directory ( aka cp SOURCE1 SOURCE2....DEST ). The pipe does not make any sense, sure, but also remains syntactically valid as far as shell is concerned - it will dup() the file descriptors just fine, it's just that reader end of the pipe won't get any data because cp doesn't write any.

        – Sergiy Kolodyazhnyy
        Feb 4 at 0:48














      • 2





        rsync, by far the easiest solution here.

        – ntk4
        Jul 18 '17 at 17:05











      • To be somewhat nitpicky, the second command cp * | grep '.prj$' ../prjshp/ does not make any sense, but can be a syntactically valid, if * expands to list of files with the last one being a directory ( aka cp SOURCE1 SOURCE2....DEST ). The pipe does not make any sense, sure, but also remains syntactically valid as far as shell is concerned - it will dup() the file descriptors just fine, it's just that reader end of the pipe won't get any data because cp doesn't write any.

        – Sergiy Kolodyazhnyy
        Feb 4 at 0:48








      2




      2





      rsync, by far the easiest solution here.

      – ntk4
      Jul 18 '17 at 17:05





      rsync, by far the easiest solution here.

      – ntk4
      Jul 18 '17 at 17:05













      To be somewhat nitpicky, the second command cp * | grep '.prj$' ../prjshp/ does not make any sense, but can be a syntactically valid, if * expands to list of files with the last one being a directory ( aka cp SOURCE1 SOURCE2....DEST ). The pipe does not make any sense, sure, but also remains syntactically valid as far as shell is concerned - it will dup() the file descriptors just fine, it's just that reader end of the pipe won't get any data because cp doesn't write any.

      – Sergiy Kolodyazhnyy
      Feb 4 at 0:48





      To be somewhat nitpicky, the second command cp * | grep '.prj$' ../prjshp/ does not make any sense, but can be a syntactically valid, if * expands to list of files with the last one being a directory ( aka cp SOURCE1 SOURCE2....DEST ). The pipe does not make any sense, sure, but also remains syntactically valid as far as shell is concerned - it will dup() the file descriptors just fine, it's just that reader end of the pipe won't get any data because cp doesn't write any.

      – Sergiy Kolodyazhnyy
      Feb 4 at 0:48













      13














      This command copies the files one by one and will work even if there are too many of them for * to expand into a single cp command:



      for i in *; do cp "$i" ../prjshp/; done





      share|improve this answer


























      • This works for me.

        – 1rq3fea324wre
        Nov 15 '17 at 18:38






      • 1





        Simple and effective. I had a similar issue removing ~1/4 million jpegs I had extracted from a video for a project. This is the approach I used.

        – Elder Geek
        Nov 26 '17 at 16:17
















      13














      This command copies the files one by one and will work even if there are too many of them for * to expand into a single cp command:



      for i in *; do cp "$i" ../prjshp/; done





      share|improve this answer


























      • This works for me.

        – 1rq3fea324wre
        Nov 15 '17 at 18:38






      • 1





        Simple and effective. I had a similar issue removing ~1/4 million jpegs I had extracted from a video for a project. This is the approach I used.

        – Elder Geek
        Nov 26 '17 at 16:17














      13












      13








      13







      This command copies the files one by one and will work even if there are too many of them for * to expand into a single cp command:



      for i in *; do cp "$i" ../prjshp/; done





      share|improve this answer















      This command copies the files one by one and will work even if there are too many of them for * to expand into a single cp command:



      for i in *; do cp "$i" ../prjshp/; done






      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Aug 24 '17 at 20:59









      Eliah Kagan

      83.5k22229369




      83.5k22229369










      answered Aug 24 '17 at 20:39









      ccshieldsccshields

      13112




      13112













      • This works for me.

        – 1rq3fea324wre
        Nov 15 '17 at 18:38






      • 1





        Simple and effective. I had a similar issue removing ~1/4 million jpegs I had extracted from a video for a project. This is the approach I used.

        – Elder Geek
        Nov 26 '17 at 16:17



















      • This works for me.

        – 1rq3fea324wre
        Nov 15 '17 at 18:38






      • 1





        Simple and effective. I had a similar issue removing ~1/4 million jpegs I had extracted from a video for a project. This is the approach I used.

        – Elder Geek
        Nov 26 '17 at 16:17

















      This works for me.

      – 1rq3fea324wre
      Nov 15 '17 at 18:38





      This works for me.

      – 1rq3fea324wre
      Nov 15 '17 at 18:38




      1




      1





      Simple and effective. I had a similar issue removing ~1/4 million jpegs I had extracted from a video for a project. This is the approach I used.

      – Elder Geek
      Nov 26 '17 at 16:17





      Simple and effective. I had a similar issue removing ~1/4 million jpegs I had extracted from a video for a project. This is the approach I used.

      – Elder Geek
      Nov 26 '17 at 16:17











      3














      There's 3 key points to keep in mind when facing Argument list too long error:




      • The length of command-line arguments is limited by ARG_MAX variable, which by POSIX definition is "...[m]aximum length of argument to the exec functions including environment data" (emphasis added)". That is, when shell executes a non-built-it command, it has to call one of exec() to spawn that command's process, and that's where ARG_MAX comes into play. Additionally, the name or path to the command itself ( for example, /bin/echo ) plays a role.


      • Shell built-in commands are executed by shell, which means the shell doesn't use exec() family of functions and therefore aren't affected by ARG_MAX variable.


      • Certain commands, such as xargs and find are aware of ARG_MAX variable and repeatedly perform actions under that limit



      From the points above and as shown in Kusalananda's excellent answer on related question, the Argument list too long can also occur when environment is big. So taking in consideration that each user's environment may vary, and the argument size in bytes is relevant, it's hard to come up with a single number of files/arguments.



      How to handle such error ?



      The key thing is to focus not on the number of files, but focus on whether or not the command you're going to use involves exec() family of function and tangentially - the stack space.



      Use shell built-ins



      As discussed before, the shell built-ins are immune to ARG_MAX limit, that is things such as for loop, while loop, built-in echo, and built-in printf - all those will perform well enough.



      for i in /path/to/dir/*; do cp "$i" /path/to/other/dir/; done


      On related question about deleting files, there was a solution as such:



      printf '%s' *.jpg | xargs -0 rm --


      Note that this uses shell's built-in printf. If we're calling the external printf, that will involve exec(), hence will fail with large number of arguments:



      $ /usr/bin/printf "%s" {1..7000000}> /dev/null
      bash: /usr/bin/printf: Argument list too long


      bash arrays



      According to an answer by jlliagre, bash doesn't impose limits on arrays, so building array of filenames and using slices per iteration of loop can be done as well, as shown in danjpreron's answer:



      files=( /path/to/old_dir/*.prj )
      for((I=0;I<${#files[*]};I+=1000)); do
      cp -t /path/to/new_dir/ "${files[@]:I:1000}"
      done


      This, however, has limitation of being bash-specific and non-POSIX.



      Increase stack space



      Sometimes you can see people suggest increasing the stack space with ulimit -s <NUM>; on Linux ARG_MAX value is 1/4th of stack space for each program, which means increasing stack space proportionally increases space for arguments.



      # getconf reports value in bytes, ulimit -s in kilobytes
      $ getconf ARG_MAX
      2097152
      $ echo $(( $(getconf ARG_MAX)*4 ))
      8388608
      $ printf "%dKn" $(ulimit -s) | numfmt --from=iec --to=none
      8388608
      # Increasing stack space results in increated ARG_MAX value
      $ ulimit -s 16384
      $ getconf ARG_MAX
      4194304


      According to answer by Franck Dernoncourt, which cites Linux Journal,
      one can also recompile Linux kernel with larger value for maximum memory pages for arguments, however, that's more work than necessary and opens potential for exploits as stated in the cited Linux Journal article.



      Avoid shell



      Another way, is to use python or python3 which come by default with Ubuntu. The python + here-doc example below, is something I personally used to copy a large directory of files somewhere in the range of 40,000 items:



      $ python <<EOF
      > import shutil
      > import os
      > for f in os.listdir('.'):
      > if os.path.isfile(f):
      > shutil.copy(f,'./newdir/')
      > EOF


      For recursive traversals, you can use os.walk.



      See also:




      • What defines the maximum size for a command single argument?






      share|improve this answer






























        3














        There's 3 key points to keep in mind when facing Argument list too long error:




        • The length of command-line arguments is limited by ARG_MAX variable, which by POSIX definition is "...[m]aximum length of argument to the exec functions including environment data" (emphasis added)". That is, when shell executes a non-built-it command, it has to call one of exec() to spawn that command's process, and that's where ARG_MAX comes into play. Additionally, the name or path to the command itself ( for example, /bin/echo ) plays a role.


        • Shell built-in commands are executed by shell, which means the shell doesn't use exec() family of functions and therefore aren't affected by ARG_MAX variable.


        • Certain commands, such as xargs and find are aware of ARG_MAX variable and repeatedly perform actions under that limit



        From the points above and as shown in Kusalananda's excellent answer on related question, the Argument list too long can also occur when environment is big. So taking in consideration that each user's environment may vary, and the argument size in bytes is relevant, it's hard to come up with a single number of files/arguments.



        How to handle such error ?



        The key thing is to focus not on the number of files, but focus on whether or not the command you're going to use involves exec() family of function and tangentially - the stack space.



        Use shell built-ins



        As discussed before, the shell built-ins are immune to ARG_MAX limit, that is things such as for loop, while loop, built-in echo, and built-in printf - all those will perform well enough.



        for i in /path/to/dir/*; do cp "$i" /path/to/other/dir/; done


        On related question about deleting files, there was a solution as such:



        printf '%s' *.jpg | xargs -0 rm --


        Note that this uses shell's built-in printf. If we're calling the external printf, that will involve exec(), hence will fail with large number of arguments:



        $ /usr/bin/printf "%s" {1..7000000}> /dev/null
        bash: /usr/bin/printf: Argument list too long


        bash arrays



        According to an answer by jlliagre, bash doesn't impose limits on arrays, so building array of filenames and using slices per iteration of loop can be done as well, as shown in danjpreron's answer:



        files=( /path/to/old_dir/*.prj )
        for((I=0;I<${#files[*]};I+=1000)); do
        cp -t /path/to/new_dir/ "${files[@]:I:1000}"
        done


        This, however, has limitation of being bash-specific and non-POSIX.



        Increase stack space



        Sometimes you can see people suggest increasing the stack space with ulimit -s <NUM>; on Linux ARG_MAX value is 1/4th of stack space for each program, which means increasing stack space proportionally increases space for arguments.



        # getconf reports value in bytes, ulimit -s in kilobytes
        $ getconf ARG_MAX
        2097152
        $ echo $(( $(getconf ARG_MAX)*4 ))
        8388608
        $ printf "%dKn" $(ulimit -s) | numfmt --from=iec --to=none
        8388608
        # Increasing stack space results in increated ARG_MAX value
        $ ulimit -s 16384
        $ getconf ARG_MAX
        4194304


        According to answer by Franck Dernoncourt, which cites Linux Journal,
        one can also recompile Linux kernel with larger value for maximum memory pages for arguments, however, that's more work than necessary and opens potential for exploits as stated in the cited Linux Journal article.



        Avoid shell



        Another way, is to use python or python3 which come by default with Ubuntu. The python + here-doc example below, is something I personally used to copy a large directory of files somewhere in the range of 40,000 items:



        $ python <<EOF
        > import shutil
        > import os
        > for f in os.listdir('.'):
        > if os.path.isfile(f):
        > shutil.copy(f,'./newdir/')
        > EOF


        For recursive traversals, you can use os.walk.



        See also:




        • What defines the maximum size for a command single argument?






        share|improve this answer




























          3












          3








          3







          There's 3 key points to keep in mind when facing Argument list too long error:




          • The length of command-line arguments is limited by ARG_MAX variable, which by POSIX definition is "...[m]aximum length of argument to the exec functions including environment data" (emphasis added)". That is, when shell executes a non-built-it command, it has to call one of exec() to spawn that command's process, and that's where ARG_MAX comes into play. Additionally, the name or path to the command itself ( for example, /bin/echo ) plays a role.


          • Shell built-in commands are executed by shell, which means the shell doesn't use exec() family of functions and therefore aren't affected by ARG_MAX variable.


          • Certain commands, such as xargs and find are aware of ARG_MAX variable and repeatedly perform actions under that limit



          From the points above and as shown in Kusalananda's excellent answer on related question, the Argument list too long can also occur when environment is big. So taking in consideration that each user's environment may vary, and the argument size in bytes is relevant, it's hard to come up with a single number of files/arguments.



          How to handle such error ?



          The key thing is to focus not on the number of files, but focus on whether or not the command you're going to use involves exec() family of function and tangentially - the stack space.



          Use shell built-ins



          As discussed before, the shell built-ins are immune to ARG_MAX limit, that is things such as for loop, while loop, built-in echo, and built-in printf - all those will perform well enough.



          for i in /path/to/dir/*; do cp "$i" /path/to/other/dir/; done


          On related question about deleting files, there was a solution as such:



          printf '%s' *.jpg | xargs -0 rm --


          Note that this uses shell's built-in printf. If we're calling the external printf, that will involve exec(), hence will fail with large number of arguments:



          $ /usr/bin/printf "%s" {1..7000000}> /dev/null
          bash: /usr/bin/printf: Argument list too long


          bash arrays



          According to an answer by jlliagre, bash doesn't impose limits on arrays, so building array of filenames and using slices per iteration of loop can be done as well, as shown in danjpreron's answer:



          files=( /path/to/old_dir/*.prj )
          for((I=0;I<${#files[*]};I+=1000)); do
          cp -t /path/to/new_dir/ "${files[@]:I:1000}"
          done


          This, however, has limitation of being bash-specific and non-POSIX.



          Increase stack space



          Sometimes you can see people suggest increasing the stack space with ulimit -s <NUM>; on Linux ARG_MAX value is 1/4th of stack space for each program, which means increasing stack space proportionally increases space for arguments.



          # getconf reports value in bytes, ulimit -s in kilobytes
          $ getconf ARG_MAX
          2097152
          $ echo $(( $(getconf ARG_MAX)*4 ))
          8388608
          $ printf "%dKn" $(ulimit -s) | numfmt --from=iec --to=none
          8388608
          # Increasing stack space results in increated ARG_MAX value
          $ ulimit -s 16384
          $ getconf ARG_MAX
          4194304


          According to answer by Franck Dernoncourt, which cites Linux Journal,
          one can also recompile Linux kernel with larger value for maximum memory pages for arguments, however, that's more work than necessary and opens potential for exploits as stated in the cited Linux Journal article.



          Avoid shell



          Another way, is to use python or python3 which come by default with Ubuntu. The python + here-doc example below, is something I personally used to copy a large directory of files somewhere in the range of 40,000 items:



          $ python <<EOF
          > import shutil
          > import os
          > for f in os.listdir('.'):
          > if os.path.isfile(f):
          > shutil.copy(f,'./newdir/')
          > EOF


          For recursive traversals, you can use os.walk.



          See also:




          • What defines the maximum size for a command single argument?






          share|improve this answer















          There's 3 key points to keep in mind when facing Argument list too long error:




          • The length of command-line arguments is limited by ARG_MAX variable, which by POSIX definition is "...[m]aximum length of argument to the exec functions including environment data" (emphasis added)". That is, when shell executes a non-built-it command, it has to call one of exec() to spawn that command's process, and that's where ARG_MAX comes into play. Additionally, the name or path to the command itself ( for example, /bin/echo ) plays a role.


          • Shell built-in commands are executed by shell, which means the shell doesn't use exec() family of functions and therefore aren't affected by ARG_MAX variable.


          • Certain commands, such as xargs and find are aware of ARG_MAX variable and repeatedly perform actions under that limit



          From the points above and as shown in Kusalananda's excellent answer on related question, the Argument list too long can also occur when environment is big. So taking in consideration that each user's environment may vary, and the argument size in bytes is relevant, it's hard to come up with a single number of files/arguments.



          How to handle such error ?



          The key thing is to focus not on the number of files, but focus on whether or not the command you're going to use involves exec() family of function and tangentially - the stack space.



          Use shell built-ins



          As discussed before, the shell built-ins are immune to ARG_MAX limit, that is things such as for loop, while loop, built-in echo, and built-in printf - all those will perform well enough.



          for i in /path/to/dir/*; do cp "$i" /path/to/other/dir/; done


          On related question about deleting files, there was a solution as such:



          printf '%s' *.jpg | xargs -0 rm --


          Note that this uses shell's built-in printf. If we're calling the external printf, that will involve exec(), hence will fail with large number of arguments:



          $ /usr/bin/printf "%s" {1..7000000}> /dev/null
          bash: /usr/bin/printf: Argument list too long


          bash arrays



          According to an answer by jlliagre, bash doesn't impose limits on arrays, so building array of filenames and using slices per iteration of loop can be done as well, as shown in danjpreron's answer:



          files=( /path/to/old_dir/*.prj )
          for((I=0;I<${#files[*]};I+=1000)); do
          cp -t /path/to/new_dir/ "${files[@]:I:1000}"
          done


          This, however, has limitation of being bash-specific and non-POSIX.



          Increase stack space



          Sometimes you can see people suggest increasing the stack space with ulimit -s <NUM>; on Linux ARG_MAX value is 1/4th of stack space for each program, which means increasing stack space proportionally increases space for arguments.



          # getconf reports value in bytes, ulimit -s in kilobytes
          $ getconf ARG_MAX
          2097152
          $ echo $(( $(getconf ARG_MAX)*4 ))
          8388608
          $ printf "%dKn" $(ulimit -s) | numfmt --from=iec --to=none
          8388608
          # Increasing stack space results in increated ARG_MAX value
          $ ulimit -s 16384
          $ getconf ARG_MAX
          4194304


          According to answer by Franck Dernoncourt, which cites Linux Journal,
          one can also recompile Linux kernel with larger value for maximum memory pages for arguments, however, that's more work than necessary and opens potential for exploits as stated in the cited Linux Journal article.



          Avoid shell



          Another way, is to use python or python3 which come by default with Ubuntu. The python + here-doc example below, is something I personally used to copy a large directory of files somewhere in the range of 40,000 items:



          $ python <<EOF
          > import shutil
          > import os
          > for f in os.listdir('.'):
          > if os.path.isfile(f):
          > shutil.copy(f,'./newdir/')
          > EOF


          For recursive traversals, you can use os.walk.



          See also:




          • What defines the maximum size for a command single argument?







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Jun 26 '18 at 1:35

























          answered Jun 26 '18 at 1:12









          Sergiy KolodyazhnyySergiy Kolodyazhnyy

          75.7k9156331




          75.7k9156331























              2














              IMHO, the optimal tools for dealing with hordes of files are find and xargs. See man find. See man xargs. find, with its -print0 switch, produces a NUL-separated list of filenames (filenames may contain any character execpt NUL or /) that xargs understands, using the -0 switch. xargs then builds the longest command allowed (the most filenames, no half-filename at the end) and executes it. xargs repeats this until find supplies no more filenames. Run xargs --show-limits </dev/null to see the limits.



              To solve your problem, (and after checking man cp to find --target-directory=):



              find . -maxdepth 1 -type f -name '*.prj' -print0 | xargs -0 cp --target-directory=../prjshp/





              share|improve this answer




























                2














                IMHO, the optimal tools for dealing with hordes of files are find and xargs. See man find. See man xargs. find, with its -print0 switch, produces a NUL-separated list of filenames (filenames may contain any character execpt NUL or /) that xargs understands, using the -0 switch. xargs then builds the longest command allowed (the most filenames, no half-filename at the end) and executes it. xargs repeats this until find supplies no more filenames. Run xargs --show-limits </dev/null to see the limits.



                To solve your problem, (and after checking man cp to find --target-directory=):



                find . -maxdepth 1 -type f -name '*.prj' -print0 | xargs -0 cp --target-directory=../prjshp/





                share|improve this answer


























                  2












                  2








                  2







                  IMHO, the optimal tools for dealing with hordes of files are find and xargs. See man find. See man xargs. find, with its -print0 switch, produces a NUL-separated list of filenames (filenames may contain any character execpt NUL or /) that xargs understands, using the -0 switch. xargs then builds the longest command allowed (the most filenames, no half-filename at the end) and executes it. xargs repeats this until find supplies no more filenames. Run xargs --show-limits </dev/null to see the limits.



                  To solve your problem, (and after checking man cp to find --target-directory=):



                  find . -maxdepth 1 -type f -name '*.prj' -print0 | xargs -0 cp --target-directory=../prjshp/





                  share|improve this answer













                  IMHO, the optimal tools for dealing with hordes of files are find and xargs. See man find. See man xargs. find, with its -print0 switch, produces a NUL-separated list of filenames (filenames may contain any character execpt NUL or /) that xargs understands, using the -0 switch. xargs then builds the longest command allowed (the most filenames, no half-filename at the end) and executes it. xargs repeats this until find supplies no more filenames. Run xargs --show-limits </dev/null to see the limits.



                  To solve your problem, (and after checking man cp to find --target-directory=):



                  find . -maxdepth 1 -type f -name '*.prj' -print0 | xargs -0 cp --target-directory=../prjshp/






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Aug 24 '17 at 22:01









                  waltinatorwaltinator

                  23.1k74269




                  23.1k74269






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Ask Ubuntu!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2faskubuntu.com%2fquestions%2f217764%2fargument-list-too-long-when-copying-files%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown