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;
}
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
add a comment |
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
Related: Does "argument list too long" restriction apply to shell builtins?
– codeforester
Nov 22 '17 at 21:19
add a comment |
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
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
command-line files
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
add a comment |
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
add a comment |
4 Answers
4
active
oldest
votes
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 {} +
findtraverses the current directory and the directories below it recursively.
-maxdepth 1means 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 thefindcommand, 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 ../prjshpmoves the specified files into../prjshp. The-toption is used here because of a limitation of thefindcommand: 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 … . ../prjshpcopies the current directory into../prjshprecursively.
--include='*.prj' --exclude='*'means to copy files matching*.prjand exclude everything else (including subdirectories, so.prjfiles in subdirectories won't be found).
2
rsync, by far the easiest solution here.
– ntk4
Jul 18 '17 at 17:05
To be somewhat nitpicky, the second commandcp * | 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 ( akacp SOURCE1 SOURCE2....DEST). The pipe does not make any sense, sure, but also remains syntactically valid as far as shell is concerned - it willdup()the file descriptors just fine, it's just that reader end of the pipe won't get any data becausecpdoesn't write any.
– Sergiy Kolodyazhnyy
Feb 4 at 0:48
add a comment |
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
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
add a comment |
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_MAXvariable, 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 ofexec()to spawn that command's process, and that's whereARG_MAXcomes 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 byARG_MAXvariable.Certain commands, such as
xargsandfindare aware ofARG_MAXvariable 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?
add a comment |
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/
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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 {} +
findtraverses the current directory and the directories below it recursively.
-maxdepth 1means 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 thefindcommand, 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 ../prjshpmoves the specified files into../prjshp. The-toption is used here because of a limitation of thefindcommand: 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 … . ../prjshpcopies the current directory into../prjshprecursively.
--include='*.prj' --exclude='*'means to copy files matching*.prjand exclude everything else (including subdirectories, so.prjfiles in subdirectories won't be found).
2
rsync, by far the easiest solution here.
– ntk4
Jul 18 '17 at 17:05
To be somewhat nitpicky, the second commandcp * | 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 ( akacp SOURCE1 SOURCE2....DEST). The pipe does not make any sense, sure, but also remains syntactically valid as far as shell is concerned - it willdup()the file descriptors just fine, it's just that reader end of the pipe won't get any data becausecpdoesn't write any.
– Sergiy Kolodyazhnyy
Feb 4 at 0:48
add a comment |
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 {} +
findtraverses the current directory and the directories below it recursively.
-maxdepth 1means 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 thefindcommand, 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 ../prjshpmoves the specified files into../prjshp. The-toption is used here because of a limitation of thefindcommand: 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 … . ../prjshpcopies the current directory into../prjshprecursively.
--include='*.prj' --exclude='*'means to copy files matching*.prjand exclude everything else (including subdirectories, so.prjfiles in subdirectories won't be found).
2
rsync, by far the easiest solution here.
– ntk4
Jul 18 '17 at 17:05
To be somewhat nitpicky, the second commandcp * | 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 ( akacp SOURCE1 SOURCE2....DEST). The pipe does not make any sense, sure, but also remains syntactically valid as far as shell is concerned - it willdup()the file descriptors just fine, it's just that reader end of the pipe won't get any data becausecpdoesn't write any.
– Sergiy Kolodyazhnyy
Feb 4 at 0:48
add a comment |
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 {} +
findtraverses the current directory and the directories below it recursively.
-maxdepth 1means 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 thefindcommand, 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 ../prjshpmoves the specified files into../prjshp. The-toption is used here because of a limitation of thefindcommand: 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 … . ../prjshpcopies the current directory into../prjshprecursively.
--include='*.prj' --exclude='*'means to copy files matching*.prjand exclude everything else (including subdirectories, so.prjfiles in subdirectories won't be found).
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 {} +
findtraverses the current directory and the directories below it recursively.
-maxdepth 1means 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 thefindcommand, 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 ../prjshpmoves the specified files into../prjshp. The-toption is used here because of a limitation of thefindcommand: 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 … . ../prjshpcopies the current directory into../prjshprecursively.
--include='*.prj' --exclude='*'means to copy files matching*.prjand exclude everything else (including subdirectories, so.prjfiles in subdirectories won't be found).
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 commandcp * | 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 ( akacp SOURCE1 SOURCE2....DEST). The pipe does not make any sense, sure, but also remains syntactically valid as far as shell is concerned - it willdup()the file descriptors just fine, it's just that reader end of the pipe won't get any data becausecpdoesn't write any.
– Sergiy Kolodyazhnyy
Feb 4 at 0:48
add a comment |
2
rsync, by far the easiest solution here.
– ntk4
Jul 18 '17 at 17:05
To be somewhat nitpicky, the second commandcp * | 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 ( akacp SOURCE1 SOURCE2....DEST). The pipe does not make any sense, sure, but also remains syntactically valid as far as shell is concerned - it willdup()the file descriptors just fine, it's just that reader end of the pipe won't get any data becausecpdoesn'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
add a comment |
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
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
add a comment |
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
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
add a comment |
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
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
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
add a comment |
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
add a comment |
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_MAXvariable, 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 ofexec()to spawn that command's process, and that's whereARG_MAXcomes 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 byARG_MAXvariable.Certain commands, such as
xargsandfindare aware ofARG_MAXvariable 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?
add a comment |
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_MAXvariable, 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 ofexec()to spawn that command's process, and that's whereARG_MAXcomes 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 byARG_MAXvariable.Certain commands, such as
xargsandfindare aware ofARG_MAXvariable 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?
add a comment |
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_MAXvariable, 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 ofexec()to spawn that command's process, and that's whereARG_MAXcomes 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 byARG_MAXvariable.Certain commands, such as
xargsandfindare aware ofARG_MAXvariable 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?
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_MAXvariable, 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 ofexec()to spawn that command's process, and that's whereARG_MAXcomes 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 byARG_MAXvariable.Certain commands, such as
xargsandfindare aware ofARG_MAXvariable 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?
edited Jun 26 '18 at 1:35
answered Jun 26 '18 at 1:12
Sergiy KolodyazhnyySergiy Kolodyazhnyy
75.7k9156331
75.7k9156331
add a comment |
add a comment |
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/
add a comment |
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/
add a comment |
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/
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/
answered Aug 24 '17 at 22:01
waltinatorwaltinator
23.1k74269
23.1k74269
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
Related: Does "argument list too long" restriction apply to shell builtins?
– codeforester
Nov 22 '17 at 21:19