When I am using this command ls repo/* | xargs -I {} cp {} backup_repo/, I am getting the error -bash: /usr/bin/ls: 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?


2 Answers 2


Use xargs --show-limits </dev/null to see your current limits.

A better way:

find repo -maxdepth 1 -type f -name '*' -print0 | \
  xargs -0 --no-run-if-empty  \
    cp --target-directory=./backup_repro/

It's a bad idea to have your backup directory in the same directory as the files you're backing up. It could lead to backing up a backup that contains a backup that contains a ... and the size of a backup approaches infinity.

Read man find xargs cp.

  • 1
    Note that -name '*' is rather pointless. It's not like shells' * glob and doesn't exclude hidden file. The only thing it does with some find implementations (including the OP's GNU find) is exclude the files whose name cannot fully be decoded as text. If you wanted to exclude hidden files, you'd need LC_ALL=C and ! -name '.*' Nov 2, 2021 at 6:07

If you just want to make a copy of repo in backup_repo, use rsync:

rsync -a repo/ backup_repo

Or, if all you need is a backup, make a tar archive,

tar -c -f repo.tar repo

If you want to copy only the visible names that * expands to inside repo, and to skip any hidden names (like .git), then you could possibly use

printf '%s\0' repo/* | xargs -0 -I {} cp -R -- {} backup_repo

or, assuming GNU cp,

printf '%s\0' repo/* | xargs -0 cp -t backup_repo -R --

The printf utility is built into the bash shell and will therefore not have the same limitation on argument list size as an external utility like ls would have.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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