Intereting Posts
Вытащить файл из контейнера Docker? Ubuntu не переходит в спящий режим после истечения срока службы батареи при закрытии крышки? Количество обратных косых черт, необходимых для экранирования обратного слэжа регулярного выражения в командной строке Архивные файлы RAR дают неполные результаты извлечения Почему разные терминалы имеют разные значения для ключей в файле .inputrc? Как навсегда избавиться от папки, которая продолжает возвращаться при перезагрузке AES-NI не передается гостю в Virtualbox Как распараллелить цикл for при scp-файлах? Как бороться с неуверенностью `eval` оценки внешнего ввода в скрипте? Разница между «man ls» и «ls –help»? как заменить выражение sed (изменить и распечатать только согласованную строку) с выражением perl? Cygwin, bash, изменить переменную окружающей среды? Результат mysql для переменной bash Спам-сообщения появляются в очереди exim, но нет пользователей электронной почты для этого домена Fish-Shell не сохранит мои псевдонимы

Итерации над 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 раз ,

Метод 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 

Вы можете использовать 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 файлов

Обновить:

Это соответствует циклу, который (я надеюсь) решает проблему с пробелами в именах файлов:

 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> eg %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] ) 

Вот версия, использующая 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 

С помощью 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 /