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

问题描述 投票:0回答:2

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

这应该很容易(对于那些可以做这样的事情的人)

我正在使用一个简单的

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

但这只是超载并给了我

Argument list too long

这个最简单的问题如何解决?

linux bash arguments
2个回答
2
投票

参数列表太长解决方法

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

getconf ARG_MAX
2097152

但是在讨论了 细节和系统(操作系统)限制之间的差异之后(请参阅其他人的评论),这个问题似乎是错误的:

关于评论的讨论,OP尝试了类似的东西:

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

发生这种情况是因为操作系统限制,而不是!!

但是用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" )

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

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

0
投票

还有一个 while 读取循环:

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
     
© www.soinside.com 2019 - 2024. All rights reserved.