我想做一些相当简单的事情。我想montage
在包含数千张图像的目录上使用,选项很少,即:
me@home$ montage -size 256x256 DSC01*.JPG.svg output.png
...但这还不够好,因为它一次只能抓取大约 100 张图像;既不是
me@home$ montage -size 256x256 *.svg output.png
...它同时抓取所有图像,因为生成的文件太大而无法解析。
我什么想做就是一次迭代 100-200 个文件。我想这可以使用 for 循环(?)来实现,但我只是对如何做到这一点有点困惑。我想可能有一种聪明的方法可以使用find -exec
或者xargs
我没有想到。我正在使用bash
,但我zsh
偶尔使用。
所以,总而言之,我正在寻找一个衬垫,给定 2600 个图像文件,调用蒙太奇大约 13 或 26 次(每个 100-200 个文件一次),给定 n 个文件,可以调用 n 次的倍数。
答案1
一种bash
方法,使用特殊的数组特征;zsh
经过一些修改可能可以翻译为:
image_files=(*.svg) # use your own glob expression
n=200 # number of files per command line; adjust to taste
for ((i=0; i < ${#image_files[@]}; i+=n)); do
montage -size 256x256 "${image_files[@]:i:n}" output-"$i".png
done
答案2
您可以使用 xargs 来实现;不幸的是,不可能将 -I (用于插入命令行中间)和 -L (用于限制对可执行文件的单次调用的文件数量)结合起来。因此,我创建了这个命令行作为示例(但要注意文件名中的特殊字符,它们不受支持):
ls . | \
xargs -n 100 echo | \
(a=1;
while read args; do
echo montage -size 256x256 $args output-$a.png;
a=$((a+1));
done
)
echo
如果你想真正执行该命令,请删除。
注意事项:
- 文件名不得包含空格或其他特殊字符
- 最后一个蒙太奇行中的文件可能少于 100 个
更新:
这是相应的 for 循环,它(我希望)可以解决文件名中的空格问题:
a=0
b=0
lst=
for f in *; do
a=$((a+1))
lst="$lst '$f'"
if test $a -ge 100; then
eval echo montage --args $lst target-$b.png
b=$((b+1))
a=0
lst=
fi
done
更新2:一个Python解决方案,应该不受文件名中特殊字符的影响
#!/usr/bin/env python
# iterate.py
"""Usage:
%prog <number per call> <file pattern> <command prefix> -- <command postfix>
e.g. %prog 100 "DSC01*.jpg.svg" montage -size 256x256 -- output-%i.png """
import sys,subprocess,glob,os
if len(sys.argv) < 5:
print __doc__.replace("%prog", os.path.basename(sys.argv[0]))
sys.exit(1)
def chunks(l, n):
for i in xrange(0, len(l), n): yield l[i:i+n]
num, pattern, args = int(sys.argv[1]), sys.argv[2], sys.argv[3:]
files, idx = glob.glob(pattern), args.index("--")
before, after = args[0:idx], args[idx+1:]
for idx,chunk in enumerate(chunks(files,num)):
subprocess.call( before + chunk + [s.replace("%i",str(idx)) for s in after] )
答案3
使用 GNU Parallel,您可以执行以下操作:
parallel -N200 montage -size 256x256 {} output{#}.png ::: *.svg
对于带有特殊字符的文件来说当然是安全的(正如您通常对 GNU Parallel 所期望的那样)。
最小化安装
如果您只需要并行并且没有安装“make”(可能系统是旧的或Microsoft Windows):
wget http://git.savannah.gnu.org/cgit/parallel.git/plain/src/parallel
chmod 755 parallel
cp parallel sem
mv parallel sem dir-in-your-$PATH/bin/
观看介绍视频以进行快速介绍: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1或 http://tinyogg.com/watch/TORaR/和http://tinyogg.com/watch/hfxKj/
答案4
这是使用 xargs 的版本,对于任何文件名都是安全的,但需要一个临时文件来存储计数。调整“-n 100”以调整每个蒙太奇的文件数量。您还可以将“printf”替换为“find -print0”,但确保它找不到“count.temp”。
echo 1 >count.temp
printf "%s\0" *.svg | xargs -0 -n 100 sh -c '
a=`cat count.temp`
montage --blah "$@" output-"$a".png
let a=a+1
echo "$a" >count.temp
'
rm count.temp