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

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

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

~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 

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

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-файлов в текущем каталоге. Мы хотим игнорировать этот список и печатать только каталог.)

  • Найти рекурсивно все архивные файлы различных форматов архивов и искать их для шаблонов имен файлов
  • Использование find и aspell вместе
  • Bash: вывод трубы «find» в «readarray»
  • Скопируйте файл и структуру файла и объедините в новый каталог
  • Как удалить старые файлы в папке в unix?
  • Копировать с помощью Find создает дубликаты файлов
  • Создание задачи Cron для уничтожения остановленных / неудачных прогонов в системе
  • Поиск файлов на сервере Unix и сортировка по размеру
  • Рефакторинг для поиска цикла для использования exec
  • Особое значение '{}' ';' с поиском
  • Прохождение результатов «находки» на зенит
  • удаление подстроки в find -exec
  • Linux и Unix - лучшая ОС в мире.