Рекурсивно перечислить все каталоги, содержащие один или несколько файлов изображений jpg

Я пытаюсь привести в порядок мои фотографии, которые по разным историческим причинам разбросаны по всей моей системе. Чтобы я мог начать работу над этой задачей, я пытался использовать командную строку для создания списка всех каталогов, содержащих один или несколько файлов jpg. Я уверен, что мне не нужно беспокоиться о поиске других форматов файлов изображений, но мне нужно разрешить появление jpg в верхнем и нижнем регистре.

Я хотел бы, чтобы каждое имя каталога отображалось только один раз в конечном списке. Чтобы привести пример, если у меня есть следующие каталоги, каждый из которых содержит один или несколько файлов JPG или JPG ….

  • Список папок верхнего уровня с содержимым не моложе 30 дней
  • Использование функции zsh в поиске?
  • Можно ли безопасно использовать `find -exec sh -c`?
  • touch & gzip все файлы HTML, CSS, JS в каталоге рекурсивно
  • Неумышленно ли я удалил весь свой жесткий диск?
  • `find` multiple -o -name условие AND! -имя
  • ~Mike/Pictures ~Mike/Pictures/London/Olympics ~Mike/Pictures/London ~Mike/Pictures/London/Holiday ~Mike/Photos ~Mike/Family History/Swaine 

    Я хотел бы, чтобы результаты отображались в каждом каталоге, указанном только один раз – независимо от количества файлов изображений, которые могут содержать, – предпочтительно отсортированы, а затем записаны в файл

     ~Mike/Family History/Swaine ~Mike/Photos ~Mike/Pictures ~Mike/Pictures/London ~Mike/Pictures/London/Holiday ~Mike/Pictures/London/Olympics 

    Мои навыки командной строки просто не до этого! Я могу использовать множество простых форм одиночных команд, но как только они становятся сложными и / или должны быть связаны с каналами, все имеет тенденцию идти не так.

  • Исключить из подстановочного знака (*), используя find
  • Сортировка вывода find -exec ls
  • Mac OS X find / grep генерирует "unknown --devices option"
  • Есть ли способ найти файл в обратном рекурсивном поиске?
  • touch & gzip все файлы HTML, CSS, JS в каталоге рекурсивно
  • Использование «find» не рекурсивно?
  • 3 Solutions collect form web for “Рекурсивно перечислить все каталоги, содержащие один или несколько файлов изображений jpg”

    Предполагая, что файлы изображений JPEG имеют суффикс .jpg :

     find "$HOME" -type f -name '*.jpg' \ -exec sh -c 'for d; do dirname "$d"; done' sh {} + | sort -u -o jpeg_dirs.txt 

    Это зависит от того, что у вас нет фанковых имен каталогов с новыми символами в их именах.

    С GNU find :

     find "$HOME" -type f -name '*.jpg' -printf '%h\n' | sort -u -o jpeg_dirs.txt 

    Эти команды find найдут все изображения JPEG в вашем домашнем каталоге и распечатают имена каталогов, где они были найдены. sort -u примет этот список имен каталогов, сортирует его и удаляет дубликаты. Результат будет записан в файл jpeg_dirs.txt в текущем каталоге.

    Простым способом является перечислить все файлы .jpg , а затем отменить базовые имена файлов (часть после последней косой черты) и удалить дубликаты. Вы можете использовать sed для разделения части каждой строки после последней косой черты. Есть команда удалить дубликаты, которые называются uniq , но он предполагает сортировку ввода; если вам все равно нужно сортировать, вы можете позволить sort выполнить уникальность.

     find ~Mike -iname '*.jpg' | sed 's!/[^/]*$!!' | sort -u >directories_with_jpeg_files.txt 

    Это предполагает, что ни один из каталогов или файлов не имеет новую строку в их имени. Имена файлов с символами новой строки не отображаются в обычных обстоятельствах, но будьте осторожны, если имена файлов могут быть выбраны враждебным лицом (например, если вы обрабатываете файлы, которые были загружены на сервер, и загрузчик может выбрать имя файла) ,

    Если есть каталоги, содержащие много файлов JPEG и не много каталогов, не содержащих JPEG-файл, этот метод тратит много времени на отчетность, а затем избыточные файлы. Невозможно сказать, что найти ярлык каталога, как только он что-то нашел в нем. Но вы можете ограничить поиск в каталогах и рассказать ему искать файл JPEG в каждом каталоге. Это увеличивает стоимость каталогов, которые не содержат файлы JPEG, однако, при наличии большого количества каталогов JPEGless может иметь низкую производительность.

     find ~Mike -type d -exec sh -c ' for d do set -- "$d/*.[Jj][Pp][Gg]"; if [ -e "$1" ]; then printf %s\\n "$d"; fi done ' sh {} + | sort -u >directories_with_jpeg_files.txt 

    В качестве альтернативы, в zsh, вы можете использовать подстановочный знак ** для рекурсивного перемещения каталогов (#i) чтобы совпадение со следующим компонентом пути не учитывалось, чтобы сделать шаблон **/(#i)*.jpg matching *.jpg и *.JPG.Jpg и т. Д.) В целом дереве каталогов. Добавьте модификатор истории h в квалификатор glob, чтобы извлечь часть каталога. Поместите это в переменную массива dirs=(…) и извлеките уникальные элементы этого массива с помощью флага расширения параметра u .

     set -o extendedglob # for (#i); best in ~/.zshrc dirs=(~Mike/**/(#i)*.jpg(:h)) print -lr -- ${(u)dirs} >directories_with_jpeg_files.txt 

    Эквивалент метода check-per-directory выше – использовать квалификатор e glob.

     print -lr ~Mike/**/*(/e\''set -- $REPLY/*.(#i)jpg(N[1]); (($# != 0))'\') >directories_with_jpeg_files.txt 
     find . -iname '*.jpg' -execdir sh -c 'pwd' _ {} + | sort -u > dirs_with_jpegs.txt 

    Должно работать достаточно хорошо, предполагая, что ваша реализация find поддерживает -execdir (это, вероятно, делает). -execdir выполняет команду в каталоге, где находится найденный файл. В этом случае мы выполняем команду pwd , которая печатает имя каталога. Мы завершаем команду sh -c чтобы разделить аргументы. (Некоторые (все?) Реализации find требуют замены {} аргумента, которая будет списком jpeg-файлов в текущем каталоге. Мы хотим игнорировать этот список и печатать только каталог.)

    Linux и Unix - лучшая ОС в мире.