脚本中的规避参数列表太长(for 循环)

Circumvent Argument list too long in script (for loop)

我已经看到了一些关于这个的答案,但作为一个新手,我真的不明白如何在我的脚本中实现它。

这应该很容易(对于那些有能力的人来说)

我使用的是简单的

for f in "/drive1/"images*.{jpg,png}; do 

但这只是超载并给我

Argument list too long

这个最简单的解决方法是什么?

参数列表太长 解决方法

参数列表长度受您的配置限制。

getconf ARG_MAX
2097152

但在讨论 specifics and system (os) limitations (see ) 之间的差异之后,这个问题似乎是错误的:

关于评论讨论,OP 尝试了类似的方法:

ls "/simple path"/image*.{jpg,png} | wc -l
bash: /bin/ls: Argument list too long

发生这种情况是因为 OS 限制,而不是 !!

但是用 OP 代码测试,这个工作很好

for file in ./"simple path"/image*.{jpg,png} ;do echo -n a;done | wc -c
70980

喜欢:

 printf "%c" ./"simple path"/image*.{jpg,png} | wc -c

通过减少固定部分来减少行长度:

第一步:您可以减少参数长度:

cd "/drive1/"
ls images*.{jpg,png} | wc -l

但是当文件数量增加时,你又会遇到错误...

更通用的解决方法:

find "/drive1/" -type f \( -name '*.jpg' -o -name '*.png' \) -exec myscript {} +

如果您不希望它是递归的,您可以添加 -maxdepth 作为第一个选项:

find "/drive1/" -maxdepth 1 -type f \( -name '*.jpg' -o -name '*.png' \) \
    -exec myscript {} +

在那里,myscript 将 运行 以文件名作为参数。 myscript 的命令行会不断增加,直到达到系统定义的限制。

myscript /drive1/file1.jpg '/drive1/File Name2.png' /drive1/...

来自 man find:

   -exec command {} +
         This  variant  of the -exec action runs the specified command on
         the selected files, but the command line is built  by  appending
         each  selected file name at the end; the total number of invoca‐
         tions of the command will  be  much  less  than  the  number  of
         matched  files.   The command line is built in much the same way
         that xargs builds its command lines.  Only one instance of  `{}'

铭文样本

您可以像这样创建脚本

#!/bin/bash

target=( "/drive1" "/Drive 2/Pictures" )

[ "" = "--run" ] && exec find "${target[@]}" -type f \( -name '*.jpg' -o \
                         -name '*.png' \) -exec [=19=] {} +

for file ;do
    echo Process "$file"
done

然后你必须 运行 以 --run 作为参数。

  • 处理 任意 个文件! (递归!参见 maxdepth 选项)

  • 允许多个target

  • 允许在文件和目录名称中使用 空格特殊字符

  • 您可以 运行 直接在文件上使用相同的脚本,而不需要 --run:

     ./myscript hello world 'hello world'
     Process hello
     Process world
     Process hello world
    

使用

使用数组,您可以执行以下操作:

allfiles=( "/drive 1"/images*.{jpg,png} )
[ -f "$allfiles" ] || { echo No file found.; exit ;}

echo Number of files: ${#allfiles[@]}

for file in "${allfiles[@]}";do
    echo Process "$file"
done

还有一个 while read 循环:

find "/drive1/" -maxdepth 1 -mindepth 1 -type f \( -name '*.jpg' -o -name '*.png' \) |
while IFS= read -r file; do

或零终止文件:

find "/drive1/" -maxdepth 1 -mindepth 1 -type f \( -name '*.jpg' -o -name '*.png' \) -print0 |
while IFS= read -r -d '' file; do