Вы говорите, что Gedit не является usng X11; который делает версия gtk-кварца это использует?
Возможно, это - osX определенный слой, используемый, который правильно не поддерживается gtk?см. также: https://bugzilla.gnome.org/show_bug.cgi? id=617583
Сценарий:
#!/bin/bash
# Get Prefixes
PREFIXES=$(ls | grep -Po '^(.*)(?!HT\d{4})-(.*)-(.*).tar.bz2$' | awk -F'-' '{print $1}' | uniq)
if [ -z "$1" ]; then
echo need a number of keep files.
exit 1
else
NUMKEEP=$1
fi
for PREFIX in ${PREFIXES}; do
ALL_FILES=$(ls -t ${PREFIX}*)
if [ $(echo ${ALL_FILES} | wc -w) -lt $NUMKEEP ]; then
echo Not enough files to be kept. Quit.
continue
fi
KEEP=$(ls -t ${PREFIX}* | head -n${NUMKEEP})
for file in $ALL_FILES ; do
if [[ "$KEEP" =~ "$file" ]]; then
echo keeping $file
else
echo RM $file
fi
done
done
Пояснение:
something-something-something.tar.bz2
, вырезать только первую часть до первого тире и сделать ее уникальной. ПРЕФИКСОВ
ПРЕФИКСАМ
: ВСЕ_ФАЙЛЫ
с помощью ПРЕФИКС
ALL_FILES
меньше, чем количество файлов, которые нужно сохранить -> если true, мы можем остановиться на этом, удалять нечего KEEP
, которые являются наиболее последние NUMKEEP
файлы ALL_FILES
и проверьте, нет ли данного файла в списке файлов KEEP
. Если так: удалите. Пример результата при запуске:
$ ./remove-old.sh 2
keeping bar-01-01.tar.bz2
keeping bar-01-02.tar.bz2
RM bar-01-03.tar.bz2
RM bar-01-04.tar.bz2
RM bar-01-05.tar.bz2
RM bar-01-06.tar.bz2
keeping foo-01-06.tar.bz2
keeping foo-01-05.tar.bz2
RM foo-01-04.tar.bz2
RM foo-01-03.tar.bz2
RM foo-01-02.tar.bz2
$ ./remove-old.sh 8
Not enough files to be kept. Quit.
Not enough files to be kept. Quit.
Как и было запрошено, этот ответ имеет тенденцию к «надежному и безопасному», как вы просили, в отличие от быстрого и грязного.
Переносимость: этот ответ работает в любой системе, содержащей sh
, find
, sed
, sort
, ls
, grep
, xargs
и rm
.
Сценарий никогда не должен заглушать большой каталог. Расширение имени файла оболочки не выполняется (что может заглушить слишком много файлов, но это огромное количество).
Этот ответ предполагает, что префикс не будет содержать тире ( -
).
Обратите внимание, что по умолчанию скрипт перечисляет только те файлы, которые будут удалены. Вы можете заставить его удалить файлы, направив вывод цикла while
в xargs -d '/ n' rm
, который закомментирован в сценарии. Таким образом, вы можете легко протестировать скрипт перед включением кода удаления.
#!/bin/sh -e
NUM_TO_KEEP=$(( 0 + ${1:-64000} )) || exit 1
find . -maxdepth 1 -regex '[^-][^-]*-[0-9][0-9]*-[0-9][0-9]*.tar.bz2' |
sed 's/-.*//; s,^\./,,' |
sort -u |
while read prefix
do
ls -t | grep "^$prefix-.*-.*\.tar\.bz2$" | sed "1,$NUM_TO_KEEP d"
done # | xargs -d '\n' rm --
Параметр N (количество сохраняемых файлов) по умолчанию равен 64000 (т. Е. Все файлы сохраняются).
Получите аргумент командной строки и проверьте целое число путем добавления, если не указано значение параметра по умолчанию 64000 (фактически все):
NUM_TO_KEEP=$(( 0 + ${1:-64000} )) || exit 1
Найти все файлы в текущем каталоге, которые соответствуют формату имени файла:
find . -maxdepth 1 -regex '[^-][^-]*-[0-9][0-9]*-[0-9][0-9]*.tar.bz2' |
Получить префикс: удалить все после префикса и удалить "./ "в начале:
sed 's/-.*//; s,^\./,,' |
Сортировка префиксов и удаление дубликатов ( -u
- уникальный):
sort -u |
Прочитать каждый префикс и обработать:
while read prefix
do
Список всех файлов в каталоге, отсортированных по времени, выберите файлы для текущего префикса и удалите все строки за пределами файлов, которые мы хотим сохранить:
ls -t | grep "^$prefix-.*-.*\.tar\.bz2$" | sed "1,$NUM_TO_KEEP d"
Для тестирования закомментируйте код для удаления файла. Использование xargs, чтобы избежать проблем с длиной командной строки или пробелами в именах файлов, если они есть . Если вы хотите, чтобы сценарий создавал журнал, добавьте -v
в rm
, например: rm -v -
. Удалите #
], чтобы активировать код удаления:
done # | xargs -d '\n' rm --
Если это сработает для вас, примите этот ответ и проголосуйте. Спасибо.
Я предполагаю, что файлы сгруппированы вместе по префиксу, если они перечислены в лексическом порядке. Это означает, что нет групп с префиксом, который является суффиксом другой группы, напримернет foo-1-2-3.tar.bz2
, который попадает между foo-1-1.tar.bz2
и foo-1-2.tar. bz2
. Исходя из этого предположения, мы можем перечислить все файлы, и когда мы обнаружим изменение префикса (или для самого первого файла), у нас появится новая группа.
#!/bin/bash
n=$1; shift # number of files to keep in each group
shopt extglob
previous_prefix=-
for x in *-+([0-9])-+([0-9]).tar.bz2; do
# Step 1: skip the file if its prefix has already been processed
this_prefix=${x%-+([0-9])-+([0-9]).tar.bz2}
if [[ "$this_prefix" == "$previous_prefix" ]]; then
continue
fi
previous_prefix=$this_prefix
# Step 2: process all the files with the current prefix
keep_latest "$n" "$this_prefix"-+([0-9])-+([0-9]).tar.bz2
done
Теперь мы подошли к проблеме определения самых старых файлов среди явного списка .
Предполагая, что имена файлов не содержат символы новой строки или символы, которые ls
не отображаются буквально, это можно реализовать с помощью ls
:
keep_latest () (
n=$1; shift
if [ "$#" -le "$n" ]; then return; fi
unset IFS; set -f
set -- $(ls -t)
shift "$n"
rm -- "$@"
)
Я знаю, что это помечено bash
, но я думаю, что это было бы проще с zsh
:
#!/usr/bin/env zsh
N=$(($1 + 1)) # calculate Nth to last
typeset -U prefixes # declare array with unique elements
prefixes=(*.tar.bz2(:s,-,/,:h)) # save prefixes in the array
for p in $prefixes # for each prefix
do
arr=(${p}*.tar.bz2) # save filenames starting with prefix in arr
if [[ ${#arr} -gt $1 ]] # if number of elements is greather than $1
then
print -rl -- ${p}*.tar.bz2(Om[1,-$N]) # print all filenames but the most recent N
fi
done
скрипт принимает один аргумент: n (количество файлов)
(:s,-,/,:h)
- модификаторы glob, :s
заменяет первые -
на /
и : h
извлекает головку (часть до последней косой черты, которая в данном случае также является первой косой чертой, так как здесь только одна)
(Om[1,-$N])
- это глобальные классификаторы, Om
сортирует файлы, начиная с самого старого, а [1,-$N]
выбирает от первого до N-го последнего
.
Если вы довольны результатом, замените print -rl
на rm
, чтобы действительно удалить файлы, например:
#!/usr/bin/env zsh
typeset -U prefixes
prefixes=(*.tar.bz2(:s,-,/,:h))
for p in $prefixes
arr=(${p}*.tar.bz2) && [[ ${#arr} -gt $1 ]] && rm -- ${p}*.tar.bz2(Om[1,-$(($1+1))])