Вопрос или проблема
Я хочу сравнить два файла в папке и удалить из названия тот номер, который меньше из двух.
Например, скажем, названия были yearMonthDay.txt
. Я хочу сравнить, какой из них меньше, и sudo rm
его.
Я знаю, что могу получить номера с помощью:
find *txt | awk -F'[_.]' '{ print $1}'
Как мне тогда следует сравнить их? Используя системные переменные? На самом деле я никогда не использовал переменные оболочки раньше.
Я предлагаю сделать что-то вроде следующего:
Я создал директорию с несколькими файлами с ‘нормальными’ датоподобными названиями, один файл с пробелом в названии (что требует кавычек) и один файл с новой строкой в названии (может вызвать проблемы, если команды, которые вы используете, предполагают, что новые строки отделяют файлы).
$ find
.
./20210710.txt
./20200131.txt
./20210611.txt
./2020?0131.txt
./20201131.txt
./2020 131.txt
Следующая командная строка использует stat
, чтобы помочь списку txt-файлов от find
,
$ find -name '*.txt' -exec stat -c '%N' {} \;
'./20210710.txt'
'./20200131.txt'
'./20210611.txt'
'./2020'$'\n''0131.txt'
'./20201131.txt'
'./2020 131.txt'
Теперь отсортируйте это (можно сделать без удаления расширения)
$ find -name '*.txt' -exec stat -c '%N' {} \; | sort
'./20200131.txt'
'./20201131.txt'
'./2020 131.txt'
'./2020'$'\n''0131.txt'
'./20210611.txt'
'./20210710.txt'
и выберите самый старый (в начале списка)
$ find -name '*.txt' -exec stat -c '%N' {} \; | sort | head -n1
'./20200131.txt'
Теперь вы можете удалить этот файл с помощью
rm $(find -name '*.txt' -exec stat -c '%N' {} \; | sort | head -n1)
Если есть риск, что будет пробел или другой специальный символ, вы хотите заключить это в кавычки (но аккуратно проверьте, чтобы избежать конфликтов с предыдущими кавычками)
rm "$(find -name '*.txt' -exec stat -c '%N' {} \; | sort | head -n1)"
Вы также можете установить переменную и использовать её в командах позже в скрипте оболочки
#!/bin/bash
find -name '*.txt' -exec stat -c '%N' {} \; | sort
var1=$(find -name '*.txt' -exec stat -c '%N' {} \; | sort | head -n1)
echo '---'
read -p "Удалить $var1? (y/N) " ans
if [ "$ans" == "y" ]
then
eval rm "$var1"
fi
С zsh
:
rm -f <->.txt(nOn[2,-1]
Среди файлов, название которых состоит из цифр, за которыми следует .txt
, удалит все, кроме одного с наибольшим номером.
Где:
<->
это форма<12-34>
без границ, поэтому соответствует любой последовательности из 1 или более десятичных цифр, аналогично[0-9]##
сextendedglob
(nOn[2,-1])
: квалификаторы glob, где:n
включает числовую сортировку.On
O
рганизует поn
азванию в обратном порядке[2,-1]
: выбирает предпоследние совпадения.
Чтобы учитывать только те, что имеют 8 цифр:
set -o extendedglob
rm -f [0-9](#c8)(On[2,-1])
Ответ или решение
Чтобы сравнить два имени файлов и удалить тот, который имеет меньший номер в названии, вам потребуется использовать оболочку командной строки, такую как Bash или Zsh. В этом ответе я объясню процесс пошагово, включая использование системных переменных и обработки строк.
Шаг 1: Получение списка файлов
На первом этапе вам нужно найти файлы с нужным форматом. Для этого вы можете использовать команду find
, которая позволит вам извлечь все файлы с расширением .txt
. Выполните следующую команду:
find . -name '*.txt'
Шаг 2: Извлечение чисел из имен файлов
Как вы верно указали, чтобы получить числа из имен файлов, вы можете использовать awk
. Однако для будущих операций лучше сохранить результат в переменной:
files=$(find . -name '*.txt' | awk -F'[_.]' '{ print $1 }')
Шаг 3: Сравнение чисел
Теперь, когда у вас есть числа из имен файлов, следующим шагом будет их сравнение для определения меньшего из них. Вы можете использовать условные операторы:
for file in $files; do
number="${file##*/}" # Убирает путь к файлу
if [[ -z $smallest || $number -lt $smallest ]]; then
smallest=$number
smallest_file="$file"
fi
done
Этот код проходит по каждому файлу и сравнивает его номер с тем, который уже сохранен в переменной smallest
. Если текущий номер меньше, он сохраняет его.
Шаг 4: Удаление файла
После того как вы определили меньший номер, вы можете удалить соответствующий файл, проверив его имя. Важно учитывать возможные пробелы и специальные символы в имени файла:
if [ -n "$smallest_file" ]; then
rm "$smallest_file"
echo "Успешно удалён файл: $smallest_file"
else
echo "Нет файлов для удаления."
fi
Завершение
В итоге, полное решение для удаления файла с меньшим номером в имени выглядело бы так:
#!/bin/bash
files=$(find . -name '*.txt' | awk -F'[_.]' '{ print $1 }')
smallest=""
for file in $files; do
number="${file##*/}"
if [[ -z $smallest || $number -lt $smallest ]]; then
smallest=$number
smallest_file="$file"
fi
done
if [ -n "$smallest_file" ]; then
rm "$smallest_file"
echo "Успешно удалён файл: $smallest_file"
else
echo "Нет файлов для удаления."
fi
Общие рекомендации
- Проверяйте наличие ошибок: При использовании
rm
лучше добавлять проверку, чтобы избежать случайного удаления нужных файлов. - Безопасность: Лучше использовать
-i
с командойrm
, чтобы избежать случайного удаления файлов, например,rm -i "$smallest_file"
.
Следуя этим шагам, вы сможете эффективно сравнивать имена файлов и удалять те из них, которые имеют меньший номер.