2

Я пытаюсь выяснить, как написать скрипт для автоматизации создания .cbz файлов из изображений в папках на OSX.

Мое дерево каталогов будет выглядеть так:

/toplevel/
cbz/
comics/
    Comic1/
        comic1file1.jpg
        comic1file2.gif
        comic1file3.png
    Comic2/
        comic2file1.jpg
        comic2file2.gif
    Publisher/
            Comic3/
                comic3file1.jpg
                comic3file2.gif
                comic3file3.png
            Comic4/
                comic4file1.jpg
                comic4file2.gif

И что я хотел бы сделать, это запустить скрипт, который найдет любую папку, содержащую реальные файлы, а не подпапки, и заархивирует ее, переименует ее из .zip в .cbz и переместит файл .cbz в папку /cbz на верхнем уровне. Любая папка, которая содержит подпапки, не должна содержать никаких файлов, так что это может быть полезно. Также я не ожидаю, что когда-либо будут подпапки глубже, чем показано в примере выше.

Где я нахожусь: этот фрагмент просматривает папку и создает .cbz-файлы для каждой подпапки.

for dir in `ls`; do zip $dir $dir/*; mv $dir*zip $dir.cbz; done

Я также нашел несколько фрагментов, которые будут выполнять что-то похожее на каждую подпапку в выбранной папке, но у меня были разные результаты, и мне было бы очень интересно узнать, как лучше всего выполнить операцию только с папками. Кроме того, я не имею понятия о том, как я должен проверить, содержит ли данная папка подпапки или файлы. (Полагаю, в идеале мне следует включить проверки, чтобы увидеть, есть ли и то и другое, но для моего текущего сценария этого не должно быть.) Есть идеи?

2 ответа2

4

Другое немного другое решение:

#!/bin/bash
find toplevel/comics -type d -not -empty -print0 | while IFS= read -r -d '' dir; do
  if find "$dir" -maxdepth 1 -type f | read f; then
    zip toplevel/cbz/"$(basename "$dir").cbz" "$dir"/*
  fi
done
  • find … -print0 | while IFS= read -r -d '' file является рекомендуемым шаблоном для перебора результатов find . Делая простую find … | while read file работает нормально, но только если возвращенные имена файлов не содержат перевода строки. Разбор ls никогда не рекомендуется.

  • find "$dir" -maxdepth 1 -type f | read f оценивает true только если файлы найдены в каталоге. Он достигает той же цели, что и оценка @ terdon числа строк, выводимых функцией find .

  • Кавычки необходимы вокруг всех переменных, чтобы пробелы в именах файлов не нарушали аргументы.

2

Прежде всего, никогда не анализируйте вывод ls. Кроме того, вы можете дать zip произвольное имя для архива, который он создаст, чтобы вам не нужно было перемещать файлы. Попробуй это:

find toplevel/comics/ -mindepth 1 -type d | 
while read dir; do 
    num=$(find "$dir" -mindepth 1 -maxdepth 1 -type f | wc -l )  
    [ "$num" -gt "0" ] && zip toplevel/cbz/"$(basename $dir)".cbd "$dir"/*; 
done

Первая find команда ищет toplevel/comics/ для каталогов type -d которые по крайней мере один уровень ниже -mindepth 1 путь дал (подкаталоги). Это гарантирует, что в результате find не вернет сам toplevel/comics . Результаты этой находки передаются по конвейеру while цикла , который обрабатывает каждый из них сохраняется в переменной $dir В каждом $dir ищутся файлы (-type f), которые фактически находятся в этом каталоге, а не в подкаталогах (-mindepth 1 -maxdepth 1). Число строк, возвращаемых функцией find (это то, что делает wc), сохраняется как $num а если оно больше 0, каталог архивируется, а архив помещается в cbz .

ЗАМЕЧАНИЯ. Архивы будут содержать полный путь к файлам (протестируйте, распаковав один из них), вы можете задать опцию -j для zip если вы этого не хотите. Смотри man zip.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .