-1

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?

Patrick
  • 39
  • 1
  • 3
  • 3
    Does this answer your question? [-bash: /usr/bin/mv: Argument list too long](https://unix.stackexchange.com/questions/675662/bash-usr-bin-mv-argument-list-too-long) – muru Nov 02 '21 at 04:22
  • 2
    You already asked this in slightly different way. – muru Nov 02 '21 at 04:22
  • Does this answer your question? [Solving "mv: Argument list too long"?](https://unix.stackexchange.com/questions/128559/solving-mv-argument-list-too-long) – rustyhu Nov 02 '21 at 05:51

2 Answers2

0

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.

waltinator
  • 4,439
  • 1
  • 16
  • 21
  • 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 '.*'` – Stéphane Chazelas Nov 02 '21 at 06:07
0

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.

Kusalananda
  • 320,670
  • 36
  • 633
  • 936