When I am using this command mv * ..
, I am getting the error -bash: /usr/bin/mv: Argument list too long
. I do understand the reason this occurs is because bash actually expands the asterisk to every matching file, producing a very long command line. How can I fix this error?
-
5Does this answer your question? Solving "mv: Argument list too long"? – Kamil Maciorowski Nov 01 '21 at 13:57
2 Answers
You could do it in two or more steps:
mv [a-k]* .. # or some other pattern matching a subset of the files
mv -- * ..
Or in a loop,
for name in *; do
mv -- "$name" ..
done
(But this would call mv
for each and every name individually.)
Or get find
to help you:
find . -mindepth 1 -maxdepth 1 -exec mv -t .. -- {} +
This would find all names in the current directory, and using GNU mv
, would move them to the directory above with as few invocations of mv
as possible.
Without GNU mv
, but with a find
that still know the non-standard -mindepth
and -maxdepth
predicates,
find . -mindepth 1 -maxdepth 1 -exec sh -c 'mv -- "$@" ..' sh {} +
None of these variations care about name collisions. You should test on data that is properly backed up.

- 333,661
-
1See
find . ! -name . -prune -exec ...
for the standard equivalent of-mindepth 1 -maxdepth 1
. Note thatfind
doesn't exclude hidden files. – Stéphane Chazelas Nov 01 '21 at 13:25
The limit is not in bash but in the execve()
system call used to execute external commands. You could do:
printf '%s\0' * | xargs -r0 mv -t .. --
Since printf
is builtin in bash
, there's no execve()
at that point. And it's xargs
job to split the list of arguments so as to avoid that limit. Here using the GNU-specific -t
option of GNU mv
.
With zsh
, you can load the mv
builtin:
zmodload zsh/files
mv -- * ..
Or use its zargs
helper to do the splitting:
autoload -Uz zargs # best in ~/.zshrc
zargs -r -- ./* -- mv -t ..
You can replace ./*
with ./*(D)
to also move hidden files or add the oN
glob qualifier to skip the sorting of file names, or the N
glob qualifier (with zargs -r
) to avoid the error if there's no matching file.
zargs -r -- ./*(ND) -- mv -t ..
Same as:
print -rNC1 ./*(ND) | xargs -r0 mv -t ..
But without the dependency to GNU xargs
.
On Linux (the kernel typically used on Ubuntu), you can also raise that execve()
limit by raising the stacksize
resource limit:
bash-5.1$ /bin/true {1..200000}
bash: /bin/true: Argument list too long
bash-5.1$ ulimit -s unlimited
bash-5.1$ /bin/true {1..200000}
bash-5.1$
It's not fully unlimited (at least not in current versions of the kernel):
bash-5.1$ /bin/true {1..2000000}
bash: /bin/true: Argument list too long
Note that the limit is on the cumulated size of the arguments and the environment variables passed to execve()
, but the computation is not just the sum of the bytes in there and how it's done varies between OS and version thereof.

- 544,893