Bash-скрипт для проверки имени каталога с условием
Я хочу исключить какой-то каталог в моем скрипте (имя каталога>1000) для удаления, и вот мой каталог выглядит так:
/home/tester/100
/home/tester/1000
/home/tester/1020 # delete all files inside
/home/tester/2000 # delete all files inside
Мой сценарий bash:
cd /home/tester
for dir in */ ; do
echo -n $dir": ";
find "$dir" -type f | wc -l;
if [ $dir -gt 1000 ]; then
cd $dir;
rm *;
cd ..;
fi
done
Я получил ошибку в строке if и понятия не имею, как ее исправить ... Можно ли сделать с помощью скрипта bash?
Спасибо за помощь
3 ответа
for dir in */ ; do
установит
dir
на такие вещи, как «1000 /» - а «/» делает это число недействительным. Вы можете обрезать завершающий "/" с помощью
${dir%/}
. Я бы также рекомендовал заключить его в двойные кавычки, чтобы предотвратить возможный странный синтаксический анализ:
if [ "${dir%/}" -gt 1000 ]; then
Обратите внимание: если имя каталога не является числом (даже после удаления "/"), вы получите сообщение об ошибке при сравнении, и
then
предложение не будет работать (что, вероятно, вы хотите). Если вы хотите более изящно обрабатывать другие (нечисловые) имена каталогов, вам следует сначала добавить соответствующий тест «is-this-a-number».
Кроме того, использование в сценариях имеет тенденцию быть проблематичным, потому что, если по какой-либо причине произойдет сбой, остальная часть сценария продолжит работу, но в неправильном месте. Это может вызвать разного рода хаос. Подумайте, что случилось бы, если бы один из
cd $dir
команды не работают: он запускается в каталоге / home / tester, удаляет там все файлы, не являющиеся подкаталогами, а затем
cd ..
, оставив его в / домой. Следующая итерация попытается сократить до чего-то вроде 2000, которого нет в / home, так что это тоже не удастся, а затем он удалит все файлы в / home. Это повторяется бесконечно, потенциально вплоть до запуска
rm *
в /, корневой каталог. Совсем не хорошо.
Я рекомендую либо проверять ошибки в командах, либо просто полностью избегать их в пользу использования явных путей к файлам.
#!/bin/bash
cd /home/tester || {
echo "Couldn't cd to /home/tester, quitting here..." >&2
exit 1
}
for dir in */ ; do
echo -n "$dir: "
find "$dir" -type f | wc -l
if [ "${dir%/}" -gt 1000 ]; then
rm "$dir"/* # Explicit path -- the / is redundant, but won't hurt
fi
done
Я также добавил явную строку shebang, заключил в двойные кавычки все ссылки на переменные (хорошая общая гигиена сценариев) и удалил точки с запятой на концах строк (не требуется в синтаксисе оболочки).
Значение
$dir
не числовой. Добавлять
set -x
в до вашего скрипта для отладки.
Использовать
"$(basename "$dir")"
чтобы получить числовое значение.
Когда у меня не было моей первой чашки кофе, я делал
for dir in */ ; do
echo -n $dir": ";
find "$dir" -type f | wc -l;
done
mv /home/tester/1000 /home/tester/some_unique_name
rm /home/tester/[1-9][0-9][0-9][0-9]/*
mv /home/tester/some_unique_name /home/tester/1000
Это не сработает, если у вас есть каталоги> 9999.
Возможно
,rm /home/tester/[1-9][0-9][0-9][0-9]*/*
будет работать, если у вас нет таких каталогов, как
1000backup
или же
2000my_unique_name
.
Лучшее решение
find . -regextype sed -regex '/home/tester/[0-9]\{4,\}' ! -name 1000 |
xargs -L1 -I{} echo rm {}/*