나는 꽤 간단한 일을 하고 싶다. 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