n개의 파일을 반복하시겠습니까?

n개의 파일을 반복하시겠습니까?

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

관련 정보