1

Как я могу удалить все каталоги / подкаталоги из дерева, которые соответствуют следующим условиям:

  1. Каталог не содержит другого подкаталога
  2. Каталог содержит только один файл, соответствующий этому шаблону регулярных выражений: ^\d {10} .jpg $ (десять цифр с расширением .jpg)

Выполнение следующей команды вернет нужные папки, но также вернет каталоги с подкаталогами

find . -type d -exec sh -c 'set -- "$0"/*.jpg; [ $# -le 1 ]' {} \; -print

2 ответа2

2

Люди увлекаются однострочниками (хотя можно писать сценарии произвольной длины, которые часто проясняют ситуацию), поэтому позвольте мне сначала сжать их в одну строку Bash :-):

shopt -s globstar; for d in **/; do f=("$d"/*); [[ ${#f[@]} -eq 1 && -f "$f" && "${f##*/}" =~ ^[0-9]{10}\.jpg$ ]] && echo rm -r -- "$d"; done

где echo является защитой во время тестирования.

Тот же код в слишком закомментированной, более читаемой версии скрипта:

#!/bin/bash

# Enable double asterisk globbing (see `man bash`).
shopt -s globstar

# Loop through every subdirectory.
for d in **/; do
    # Glob a list of the files in the directory.
    f=("$d"/*)
    # If
    # 1. there is exactly 1 entry in the directory
    # 2. it is a file
    # 3. the file name consists of 10 digits with a ".jpg" suffix:
    if [[ ${#f[@]} -eq 1 && -f "$f" && "${f##*/}" =~ ^[0-9]{10}\.jpg$ ]]; then
        # `echo` to ensure a test run; remove when verified.
        echo rm -r -- "$d"
    fi
done

Соответствие - чистый Bash (версия ≥4), и я считаю, что он не уязвим для "хитрых" имен файлов из-за сбоев. По умолчанию он работает из текущего каталога, но его можно изменить для работы с заданным аргументом, жестко заданным путем и т.д.


ДОПОЛНЕНИЕ: Для запуска в обратном порядке глобализации подкаталогов, чтобы избежать необходимости выполнять многократные итерации, если это является проблемой, можно сначала сохранить подкаталоги в переменной, а затем пересмотреть ее в обратном направлении, например так:

#!/bin/bash

# Enable double asterisk globbing (see `man bash`).
shopt -s globstar

# Glob every subdirectory.
subdirs=(**/)

# Loop directories in backwards lexical order to avoid multiple iterations.
for ((i=${#subdirs[@]}; i>0; --i)); do
    d=${subdirs[i-1]}
    # Glob a list of the files in the directory.
    f=("$d"/*)
    # If
    # 1. there is exactly 1 entry in the directory
    # 2. it is a file
    # 3. the file name consists of 10 digits with a ".jpg" suffix:
    if [[ ${#f[@]} -eq 1 && -f "$f" && "${f##*/}" =~ ^[0-9]{10}\.jpg$ ]]; then
        # `echo` to ensure a test run; remove when verified.
        echo rm -r -- "$d"
    fi
done

Я думаю, что это решит проблему в комментарии, где некоторые каталоги могут быть удалены только после обработки подкаталогов (я не буду обновлять однострочник, но каждый может сделать это для себя сам :-)).

0

Сохраните вывод вашей команды и вывод этой команды:

ls -lR | awk -F: '!($0 ~ ORS "d") && $0 ORS ~ "-" {print $1}' RS=

(Этот находит каталоги без подкаталогов)

И используйте команду "comm" для проверки похожих строк?

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