Если у вас есть bash 4+ (проверьте с помощью bash --version
), вы можете сделать это в две строки:
shopt -s globstar
for f in ./**/; do [[ -f "$f"/DONOTDELETE.TXT ]] || rm -f "$f"/*; done
Обратите внимание, что shopt -s globstar
должен находиться на отдельной строке - не просто добавлять его к циклу for с помощью ;
,
./**/
расширяется до каждого подкаталога в текущем каталоге, и их подкаталоги рекурсивно. Если вы хотите пройти вниз по дереву только на один уровень, используйте вместо этого ./*/
(и не беспокойтесь о настройке globstar); если вам нужен более точный контроль, вам придется возиться с find
(в частности, с -maxdepth
и -mindepth
). Я использую ./**/
вместо **/
в случае, если любой из ваших каталогов начинается с -
: это мешает их видеть как
[[ -f "$f"/DONOTDELETE.TXT ]]
проверяет, существует ли этот файл и является ли он файлом (если вы хотите, чтобы он работал, даже если DONOTDELETE.TXT может отличаться от файла, используйте -e
вместо -f
). Строго говоря, вам не нужен /
in, так как $ f содержит косую черту, но я думаю, что в этом случае она выглядит лучше, и в целом избыточные косые черты безвредны. ||
означает ИЛИ - если (и только если) этот тест оценивается как ложный, то будет выполнен код справа от него, в этом случае rm -f "$f"/*
- который удаляет все файлы, кроме скрытых.
Если вы также хотите удалить скрытые файлы, вы можете использовать что-то вроде:
for f in ./**/; do [[ -f "$f"/DONOTDELETE.TXT ]] || rm -f "$f"/* "$f"/.*; done