Как удалить самый старый каталог в данном каталоге?

Возможный дубликат:
Сценарий оболочки для перемещения старых файлов?

У меня есть резервный каталог, в котором хранятся x других каталогов, требующих резервного копирования. Мне нужно что-то, что будет выполняться до того, как другой каталог будет перемещен в резервную копию, что будет проверять, достигло ли количество каталогов x и если оно есть, оно удалит самый старый каталог.

Это должно быть сделано в сценарии bash .

3 Solutions collect form web for “Как удалить самый старый каталог в данном каталоге?”

Разбор вывода ls не является надежным .

Вместо этого используйте find для поиска каталогов и sort чтобы упорядочить их по метке времени. Например:

 IFS= read -r -d $'\0' line < <(find . -maxdepth 1 -type d -printf '%T@ %p\0' \ 2>/dev/null | sort -z -n) file="${line#* }" # do something with $file here 

Что все это делает?

Во-первых, команды find обнаруживают все каталоги в текущем каталоге ( . ), Но не в подкаталогах текущего каталога ( -maxdepth 1 ), а затем распечатывают:

  • Временная метка
  • Пространство
  • Относительный путь к файлу
  • Символ NULL

Временная метка важна. Спецификатор формата %T@ для -printf разбивается на T , что указывает «Время последней модификации» файла (mtime) и @ , что указывает «Секунды с 1970 года», включая дробные секунды.

Пространство является просто произвольным разделителем. Полный путь к файлу состоит в том, что мы можем ссылаться на него позже, а символ NULL – это терминатор, поскольку он является незаконным символом в имени файла и, таким образом, позволяет нам точно знать, что мы достигли конца пути к файл.

Я включил 2>/dev/null поэтому файлы, у которых пользователь не имеет доступа к доступу, исключены, но сообщения об ошибках об их исключении подавляются.

Результатом команды find является список всех каталогов в текущем каталоге. Список sort по sort которому поручено:

  • -z Обработать NULL как символ терминатора линии вместо новой строки.
  • -n Сортировка численно

Поскольку секунды с 1970 года всегда идут вверх, мы хотим, чтобы файл с меткой времени был наименьшим числом. Первым результатом sort будет строка, содержащая наименьшую пронумерованную временную метку. Осталось только извлечь имя файла.

Результаты find , конвейер sort передаются через замещение процесса, чтобы read , где он читается так, как если бы это был файл на stdin.

В контексте read мы устанавливаем переменную IFS в ничто, а это означает, что пробел не будет неправильно интерпретирован как разделитель. read -r , который отключает расширение -d $'\0' и -d $'\0' , что делает ограничитель конца строки NULL, соответствующий выходу из нашего find , sort конвейер.

Первый фрагмент данных, представляющий самый старый путь каталога, которому предшествует его метка времени и пробел, считывается в переменную line . Затем подстановка параметра используется с выражением #* , которое просто заменяет все символы от начала строки до первого пространства, включая пробел, и ничего. Это отбрасывает временную метку модификации, оставляя только полный путь к файлу.

На этом этапе имя файла сохраняется в $file и вы можете делать с ним все, что вам нравится, в том числе rm -rf "$file" .

Разве нет более простого способа?

Нет. Упрощенные способы ошибочны.

Если вы используете ls -t и pipe to tail вы разбиваете файлы с новыми символами в именах файлов. Если вы rm $(anything) то файлы с пробелами в имени вызовут поломку. Если вы rm "$(anything)" то файлы с завершающими символами новой строки в имени вызовут поломку.

Возможно, в конкретных случаях вы точно знаете, что более простой способ является достаточным, но вы никогда не должны писать такие предположения, как в сценариях, если вы можете этого не делать.

редактировать

 #!/usr/bin/env bash dir="$1" min_dirs=3 [[ $(find "$dir" -maxdepth 1 -type d | wc -l) -ge $min_dirs ]] && IFS= read -r -d $'\0' line < <(find "$dir" -maxdepth 1 -printf '%T@ %p\0' 2>/dev/null | sort -z -n) file="${line#* }" ls -lLd "$file" 

Более полное решение проблемы, так как она сначала проверяет количество дисков.

вы можете использовать что-то вроде folliwing:

 #!/bin/sh keep=3 while [ `ls -1 | wc -l` -gt $keep ]; do oldest=`ls -c1 | head -1` echo "remove $oldest" rm -rf $oldest done 

было бы лучше использовать find . -type d -maxdepth 1 find . -type d -maxdepth 1 а не ls . это зависит от схемы именования, которую вы используете для каталогов. если они естественным образом отсортированы по их имени, вы можете использовать find , sort и head или tail чтобы получить старейший / новейший каталог. в подходе ls используется атрибут ctime для сортировки.

Попробуйте:

 rm $(ls -t1 | tail -n 1) 
  • Как проверить, существует ли один или оба из двух файлов?
  • Посмотрите, есть ли в папке несколько файлов с определенными расширениями
  • избегать множественных труб, поврежденных из-за отсутствия команды
  • TeXstudio: открыть файл на номер строки n
  • Измените файл без создания другого файла
  • Установка переменной среды с помощью сценария оболочки
  • сценарий оболочки для добавления идентификатора для команды newusers
  • Как сгенерировать Zipf-подобные образцы, используя язык сценариев
  • Значение параметра не устраняется
  • Есть ли способ создать бесконечный поток с пользовательским характером?
  • Команда, работающая от CLI, но не от скрипта
  • Sudo в качестве другого пользователя, чтобы сохранить свой домашний каталог в txt-файле
  • Interesting Posts

    Можно ли находить файлы, созданные между двумя конкретными временами, игнорируя даты?

    Как управлять установленными из исходных программ?

    Запустить скрипт без ./ перед именем

    Почему я получаю «недопустимый максимальный счет» из grep в псевдониме?

    Как определить общие файлы, открытые с помощью userid

    Как получить выход из Nagios в файле

    Как я могу быстро проверить, сколько столбцов у моего терминала?

    Добавить строку суффикса в конец каждой строки?

    Как перенастроить grub на резервном архиве linux на флэш-диске USB

    Разрешения пользователя и группы для доступа к файлам и файлам mnt в CentOS 7

    Почему пакеты поставляются без скриптов init.d?

    Чтение umask для пользователя

    emacs выделенное окно завершения

    Клиент OpenVPN получает новый ip для каждой загрузки, как получить тот же адрес в x время ожидания?

    Как мне изменить адрес FROM с помощью mailx на FreeBSD из командной строки?

    Linux и Unix - лучшая ОС в мире.