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, заключил в двойные кавычки все ссылки на переменные (хорошая общая гигиена сценариев) и удалил точки с запятой на концах строк (не требуется в синтаксисе оболочки).

Еще одна рекомендация: запускайте свои скрипты через shellcheck.net - он <ahref="https: rel="nofollow noreferrer" translate.google.com="" website?sl='en&tl=ru&u=https://www.shellcheck.net"'>укажет на множество распространенных ошибок, таких как ссылки на переменные без <ahref="https: rel="nofollow noreferrer" translate.google.com="" website?sl='en&tl=ru&u=https://www.shellcheck.net"'>кавычек и отсутствие флажков.<tcode id="4224952"></tcode>с.</ahref="https:></ahref="https:>

Значение $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 {}/* 
Другие вопросы по тегам