Zsh glob для поиска пустых каталогов или содержащих только .DS_Store

Есть ли какой-нибудь zsh glob, который найдет пустые каталоги или содержащие только файл .DS_Store?

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

Для моих целей, если я не могу отфильтровать конкретно .DS_Store, достаточно отфильтровать все скрытые файлы (.*).

Поскольку это взаимоисключающие запросы, попробуйте find /directory -empty -type d, тогда find /directory -name ".DS_Store"

Andre Wildberg 09.08.2024 13:52

Я пытаюсь использовать glob, чтобы сохранить его родным для zsh для обеспечения переносимости и производительности, и чтобы я мог научиться использовать более продвинутые функции zsh. К вашему сведению: у find есть оператор -or, поэтому два вызова find можно объединить.

XDR 09.08.2024 14:19

Кто бы ни голосовал за закрытие: почему?

XDR 09.08.2024 14:27

С точки зрения производительности и портативности я бы сказал, используйте find. Использование -o (совместимо с POSIX) может довольно быстро усложниться, но это субъективно.

Andre Wildberg 09.08.2024 14:31

Это похоже на apple.stackexchange.com в частности, unix.stackexchange.com в целом или superuser.com в крайнем случае.

tevemadar 09.08.2024 17:29

Суть этого вопроса не относится только к macOS. То же решение будет работать с zsh на любой платформе. В Stack Overflow более 6,1 тыс. вопросов по zsh, в Unix — более 3 тыс., в суперпользователе — более 1,4 тыс., а в Ask Different — более 400, поэтому я выбрал Stack Overflow.

XDR 10.08.2024 02:18

Для всех «скрытых файлов» в дереве каталогов ниже каталога top следует использовать top/**/.*(ND).

user1934428 12.08.2024 15:43

@user1934428 user1934428 Я хочу отфильтровать .DS_Store или все скрытые файлы.

XDR 12.08.2024 19:15
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
8
82
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

В результате должен появиться список каталогов, в которых есть только файл .DS_Store:

checkDir() {
    setopt extendedglob localoptions
    REPLY=${${REPLY:h}:-.}
    local -a files=($REPLY/^.DS_Store(NDY1))    
    return ${#files}
}
print -lr -- **/.DS_Store(.+checkDir)

Он использует квалификатор +glob для фильтрации совпадающих результатов. Некоторые из частей:

  • **/.DS_Store(.+checkDir) — начальный оператор glob:
    • **/ — поиск по текущему каталогу и его подкаталогам.
    • .DS_Store — файлы с именем .DS_STORE.
    • (.) — включать только обычные файлы.
    • (+checkDir) - проверьте каждый результат с помощью функции checkDir.
  • checkDir() ... - zsh функция:
    • setopt extendedglob localoptions — включить расширенные операторы glob. При использовании localoptions настройка будет применяться только к этой функции.
    • REPLY=${${REPLY:h}:-.}REPLY является одновременно входными и выходными данными функции.
      • ${REPLY:h} — входные данные — путь к файлу .DS_Store; это даст нам базовый каталог (hhead).
      • ${...:-.} - если каталог пуст, файл находится в текущем каталоге - установите отображаемый результат на ..
    • local -a files=($REPLY/^.DS_Store(NDY1)) — построить список файлов в каталоге в REPLY.
      • $REPLY/^.DS_Store — с ^ в списке будут файлы без имени .DS_Store.
      • (N) - нет ошибки, если список пуст (Null).
      • (D) — включать имена файлов, начинающиеся с ..
      • (Y1) - короткое замыкание. Только проверка на наличие файлов; это остановит построение списка, если что-нибудь будет найдено.
    • return ${#files} — установите код возврата для функции.
      • $#files == 0 — включите в результаты имя каталога, хранящееся в REPLY.
      • $#files != 0 — исключить эту запись из результатов.

Пустые каталоги можно добавить, объединив приведенное выше выражение glob с другим выражением, использующим квалификатор (/^F):

=> print -lr -- **/ **/*(.D) | sort
aa/
bb/
bb/.DS_Store
cc/
cc/.DS_Store
cc/anotherfile
=> print -lr -- **/.DS_Store(N.+checkDir) **/*(N/^F)
bb
aa
=> cd bb
=> print -lr -- **/.DS_Store(N.+checkDir)
.

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

print -lr -- **/(e{'fl=($REPLY/*(NY1));((!$#fl))'})

Обозначение $REPLY/^.DS_Store вполне достоверно!

hchbaw 11.08.2024 11:23
Ответ принят как подходящий

Не просто, но мы могли бы сделать:

setopt extendedglob  # for '~' and '#q' in the `[[ … ]]' form
setopt globstarshort # shortcut for '**/*' to '**'

print -rC1 -- **(DN/^F,/e['[[ -z $REPLY/*~*/.DS_Store(#qoNDNY1) ]]'])

перечисляет пустые каталоги или каталоги, в которых не существует ни одного файла кроме .DS_Store (другими словами: выходит только .DS_Store).

  • **(…): GLOB_STAR_SHORT ярлык для **/*.

  • *(…): Глоб отборочные указать, какие имена файлов, которые в противном случае соответствуют данному шаблону, будут быть вставлен в список аргументов.

  • D: набор GLOB_DOTS, включить точечные файлы, каталоги.

  • N: набор NULL_GLOB, не сигнализировать об ошибке, если шаблон не соответствует. (Не требуется для особенно тестирование/экспериментирование.)

  • /^F: идиома zsh для пустых каталогов.

  • ,: ИЛИ

  • /e[…]: каталоги И eстроковый квалификатор, обозначающий каталоги которые соответствуют строке кода zsh, то есть .

  • [[ -z … ]]: будет описано, что другого файла, кроме .DS_Store, не существует. используя глобальные шаблоны.

  • $REPLY: во время выполнения e[…] имя файла в данный момент проверено, в этом случае имя каталога будет передано через zsh.

  • *~*/.DS_Store: X~Y означает совпадение всего, что соответствует шаблону. X но не совпадает Y. Таким образом, он будет расширять что-либо, кроме .DS_Store.

  • #q: подстановка выполняется в форме [[ -z … ]].

  • oN: нет.

  • D: GLOB_DOTS снова.

  • N: набор NULL_GLOB, пусть zsh не сигнализирует об ошибке во время обработки e[…].

  • Y1: короткое замыкание, будет учитываться только первое совпадение. достаточно.

setopt extendedglob globstarshort
rm -rf tester
mkdir tester
cd tester
mkdir empty dsstore-only more-dotfiles more
touch dsstore-only/.DS_Store more-dotfiles/{.DS_Store,.DS_Store.old} more/{.DS_Store,more}
mkdir child
cp -a ^child child
tree -a
#>> .
#>> ├── child
#>> │   ├── dsstore-only
#>> │   │   └── .DS_Store
#>> │   ├── empty
#>> │   ├── more
#>> │   │   ├── .DS_Store
#>> │   │   └── more
#>> │   └── more-dotfiles
#>> │       ├── .DS_Store
#>> │       └── .DS_Store.old
#>> ├── dsstore-only
#>> │   └── .DS_Store
#>> ├── empty
#>> ├── more
#>> │   ├── .DS_Store
#>> │   └── more
#>> └── more-dotfiles
#>>     ├── .DS_Store
#>>     └── .DS_Store.old
#>>
#>>10 directories, 10 files

print -rC1 -- **(DN/^F,/e['[[ -z $REPLY/*~*/.DS_Store(#qoNDNY1) ]]'])
#>> child/dsstore-only
#>> child/empty
#>> dsstore-only
#>> empty

Примечание: некоторые ссылки:

Glob Qualifires:
...
Можно объединить несколько таких списков, разделив их запятыми. весь список соответствует, если совпадает хотя бы один из подсписков (они `or'ed, квалификаторы в подсписках имеют `and'ed). Некоторый квалификаторы,

--- Glob Qualifires, zshexpn(1)

Условные выражения:
...
Генерация имени файла не выполняется ни для какой формы аргумента. условия. Однако его можно принудительно выполнить в любом случае, когда обычная оболочка расширение допустимо, и когда действует опция EXTENDED_GLOB, используя явный квалификатор glob формы (#q) в конце нить.

--- Условные выражения, zshmisc(1)

Ааа, я пытался заставить [[ -z <glob> ]] работать, похоже, мне нужны были и extendedglob, и формат квалификатора (#q...). Кое-что узнал - спасибо!

Gairfowl 11.08.2024 11:48

Другие вопросы по теме

Как эффективно выполнять параллельный поиск файлов с использованием pathlib `glob` в Python для больших структур каталогов?
Как я могу объединить несколько файлов CSV в один лист Excel с помощью Python?
Powershell & bash: получить все файлы, соответствующие каталогу по пути и имени файла
Мой код работает только с одним файлом изображения, остальные файлы изображений считываются и сохраняются, но мой код не затрагивает их. Мне нужно, чтобы мой код работал со всеми файлами изображений
Определите входные файлы для Snakemake, используя glob
Как использовать windows_expand_args с программой щелчка одной командой
Как я могу исключить базовый каталог из рекурсивного glob в Python?
Почему мой шаблон исключения Glue Crawler не применяется?
Как использовать шаблон glob для поиска файлов в скрытых каталогах с помощью zsh
Bash case glob, чтобы соответствовать части имени хоста и игнорировать последние символы

Похожие вопросы