在 bash shell 中将文件从一个目录移动到另一个目录时,参数列表对于 ls 来说太长
Argument list too long for ls while moving files from one dir to other in bash shell
下面是我用于将文件从目录 a
移动到目录 b
的命令
ls /<someloc>/a/* | tail -2000 | xargs -I{} mv {} /<someloc>/b/
-bash: /usr/bin/ls: Argument list too long
文件夹 a
有数百万个文件..
需要你的帮助来解决这个问题。
如果两个目录的位置在同一个disk/partition上,并且文件夹b
原来是空的,您可以执行以下操作
$ rmdir /path/to/b
$ mv /other/path/to/a /path/to/b
$ mkdir /other/path/to/a
如果文件夹 b
不为空,那么您可以这样做:
find /path/to/a/ -type f -exec mv -t /path/to/b {} +
如果你只想移动2000个文件,你可以这样做
find /path/to/a/ -type f -print | tail -2000 | xargs mv -t /path/to/b
但这对于某些文件名可能会有问题。更简洁的方法是使用 -print0
of find
,但问题是 head
和 tail
无法处理这些,因此您必须使用 awk
为此。
# first 2000 files (mimick head)
find /path/to/a -type f -print0 \
| awk 'BEGIN{RS=ORS="[=13=]"}(NR<=2000)' \
| xargs -0 mv -t /path/to/b
# last 2000 files (mimick tail)
find /path/to/a -type f -print0 \
| awk 'BEGIN{RS=ORS="[=13=]"}{a[NR%2000]=[=13=]}END{for(i=1;i<=2000;++i) print a[i]}' \
| xargs -0 mv -t /path/to/b
问题代码中的ls
没有任何用处。 glob (/<someloc>/a/*
) 生成一个排序的文件列表,ls
只是复制它(在重新排序之后),如果它可以工作的话。请参阅 “Argument list too long”: How do I deal with it, without changing my command? 以了解 ls
失败的原因。
使代码正常工作的一种方法是将 ls
替换为 printf
:
printf '%s\n' /<someloc>/a/* | tail -2000 | xargs -I{} mv {} /<someloc>/b/
printf
是一个 Bash 内置函数,因此 运行 它不会创建子进程,因此不会出现 "Argument list too long" 问题。
如果任何文件的名称中包含换行符,此代码仍然会失败。请参阅 kvantour 的回答,了解不易受此问题影响的替代方案。
下面是我用于将文件从目录 a
移动到目录 b
ls /<someloc>/a/* | tail -2000 | xargs -I{} mv {} /<someloc>/b/
-bash: /usr/bin/ls: Argument list too long
文件夹 a
有数百万个文件..
需要你的帮助来解决这个问题。
如果两个目录的位置在同一个disk/partition上,并且文件夹b
原来是空的,您可以执行以下操作
$ rmdir /path/to/b
$ mv /other/path/to/a /path/to/b
$ mkdir /other/path/to/a
如果文件夹 b
不为空,那么您可以这样做:
find /path/to/a/ -type f -exec mv -t /path/to/b {} +
如果你只想移动2000个文件,你可以这样做
find /path/to/a/ -type f -print | tail -2000 | xargs mv -t /path/to/b
但这对于某些文件名可能会有问题。更简洁的方法是使用 -print0
of find
,但问题是 head
和 tail
无法处理这些,因此您必须使用 awk
为此。
# first 2000 files (mimick head)
find /path/to/a -type f -print0 \
| awk 'BEGIN{RS=ORS="[=13=]"}(NR<=2000)' \
| xargs -0 mv -t /path/to/b
# last 2000 files (mimick tail)
find /path/to/a -type f -print0 \
| awk 'BEGIN{RS=ORS="[=13=]"}{a[NR%2000]=[=13=]}END{for(i=1;i<=2000;++i) print a[i]}' \
| xargs -0 mv -t /path/to/b
问题代码中的ls
没有任何用处。 glob (/<someloc>/a/*
) 生成一个排序的文件列表,ls
只是复制它(在重新排序之后),如果它可以工作的话。请参阅 “Argument list too long”: How do I deal with it, without changing my command? 以了解 ls
失败的原因。
使代码正常工作的一种方法是将 ls
替换为 printf
:
printf '%s\n' /<someloc>/a/* | tail -2000 | xargs -I{} mv {} /<someloc>/b/
printf
是一个 Bash 内置函数,因此 运行 它不会创建子进程,因此不会出现 "Argument list too long" 问题。
如果任何文件的名称中包含换行符,此代码仍然会失败。请参阅 kvantour 的回答,了解不易受此问题影响的替代方案。