Вопрос или проблема
Я работаю над скриптом cron для сортировки/фильтрации, чтобы обрабатывать входящие файлы на основе набора постоянных строк (logfile, history, dataset и т. д.). Файлы, которые нужно отсортировать, находятся в общей папке: некоторые в основной папке, а некоторые в подпапках. Я работаю над этим на Debian/bash (MX Linux), и это моя основная забота на данный момент, но в итоге это будет перенесено на систему Debian/ash (dCore Linux).
- имена файлов и папок всегда содержат STRING, и STRING может содержать смешанный регистр.
- имя файла и подпапка, в которой он находится, могут оба содержать STRING.
- папки с STRING могут содержать файлы без STRING. Они должны перемещаться вместе с их родительскими папками.
- имена файлов и папок могут содержать пробелы, скобки, скобки.
пример:
/main/ # папка, в которой идет поиск
/main/filename.log # не должен быть перемещен
/main/filename containing-STRING.log # должен быть перемещен
/main/subfolder/ # не должен быть перемещен
/main/subfolder/file.txt # не должен быть перемещен
/main/subfolder.with STRING in-name/ # должен быть перемещен
/main/subfolder.with STRING in-name/STRING-file.log # должен быть перемещен вместе с родительской папкой
/main/subfolder.with STRING in-name/file.txt # должен быть перемещен вместе с родительской папкой
Моя отправная точка:
find . -iname '*STRING*' -exec mv {} ../offload/ \;
Это работает, хотя и выдает ошибки “файл не найден”, предположительно потому, что файлы уже были перемещены, когда их родительские папки были перемещены. Поскольку любые подпапки всегда будут содержать STRING, мне не обязательно нужно или я не хочу ‘искать’ их содержимое. Мне нужно переместить только родительские папки. Поэтому я пытаюсь использовать ‘-maxdepth 0’, чтобы ‘найти’ STRING только в основной папке.
find . -maxdepth 0 -iname '*STRING*' -exec mv {} ../offload/ \;
Добавление переключателя -maxdepth не работает. Предупреждений “файл не найден” нет, но ничего не перемещается. Есть ли какие-то предложения, в чем я ошибаюсь?
РЕДАКТИРОВАНИЕ:
У меня есть доступ только к оболочке bash и в конечном итоге к системе dCore с ее стандартной оболочкой ash. Это мини-система только с интерфейсом командной строки; нет места для добавления другой оболочной среды.
Я пробовал:
find . -maxdepth 0 -type d -iname '*STRING*' -exec mv {} ../offload/ \;
Когда я запускаю его, он возвращает меня к приглашению без ошибок, но ничего не перемешается.
@cas Да, мне нужно сохранить структуру каталогов, но ни один из ваших примеров не должен удовлетворять поиску. Я хочу только найти и переместить файлы и каталоги, которые соответствуют STRING в основной папке. Таким образом:
/main/filename-with-STRING # соответствует
/main/folder-with-STRING/ # соответствует
/main/folder-with-STRING/foo/ # перемещен вместе с родителем
/main/subfolder/filename-with-STRING # не соответствует
/main/subfolder/folder-with-STRING/ # не соответствует
Похоже, вы сначала захотите переместить все соответствующие директории, а затем все файлы, символические ссылки и т. д., которые остались и соответствуют.
Вы можете сделать это, указав -type d
для директорий в первом запуске find
и '(' -not -type d ')'
для второго запуска find
.
Однако, вы можете сделать это и без find
, используя современную оболочку:
#!/usr/bin/zsh
# возможно, уже включено! Так что, просто для справки:
setopt extended_glob
# также учитывать "скрытые" файлы, т.е., такие, которые начинаются с точки
setopt dotglob
# нам не важен регистр!
setopt nocaseglob
# переместить все директории.
mv **/*STRING*(/) ../offload/
# переместить все, что не директории
mv **/*STRING*(^/) ../offload/
Ответ или решение
В целях решения вашей задачи по перемещению файлов и папок, содержащих определённую подстроку (STRING), давайте подробно разберём, как оптимально использовать команду find
с параметром -maxdepth
в вашем сценарии.
Теория
Ваша цель заключается в том, чтобы перемещать только те файлы и папки, которые содержат подстроку "STRING" в их именах и расположены в основном каталоге. Недостаток вашего начального подхода состоит в том, что, используя -maxdepth 0
, вы ограничиваете поиск только текущей директорией (.
), что приводит к полному исключению всех подкаталогов и их содержимого из поиска. Параметр -maxdepth 0
означает, что поиск будет ограничен текущей директорией, и любые вложенные папки или файлы из другого уровня не будут найдены.
Пример
Рассмотрим, как нужно использовать команду find
. Исходя из вашего описания, вам нужно переместить папки, содержащие "STRING", и находящиеся в основном каталоге, а также файлы в основном каталоге, которые содержат "STRING".
Пример использования:
# Сначала перемещаем директории из корневого каталога, содержащие "STRING" в имени
find . -maxdepth 1 -type d -iname '*STRING*' -exec mv {} ../offload/ \;
# Затем перемещаем файлы из корневого каталога, содержащие "STRING" в имени
find . -maxdepth 1 -type f -iname '*STRING*' -exec mv {} ../offload/ \;
Применение
Данный подход позволяет сначала перемещать все директории, соответствующие критерию поиска, а затем — все файлы в основном каталоге. Команда find
с опцией -maxdepth 1
ограничивает глубину поиска, тем самым предотвращая перемещение объектов внутри подкаталогов. Использование -type d
и -type f
позволяет различать директории и обыкновенные файлы, отдельно обрабатывая их перемещение.
Важно убедиться, что в целевой директории ../offload/
у вас достаточно места и прав для записи, так как при большом объёме перемещаемых данных могут возникнуть ошибки, связанные с доступностью ресурсов.
Аппаратное окружение Debian/Bash позволит вам корректно использовать эти команды. В случае перехода на dCore Linux с оболочкой ash, убедитесь, что она поддерживает заданные параметры, или используйте аналогичные скрипты, обеспечивающие указанную функциональность.
Таким образом, внимательно настроив параметры команды find
, вы сможете эффективно выполнять сортировку и перемещение требуемых файлов и папок по заданным условиям.