Как сравнить два имени файла

Вопрос или проблема

Я хочу сравнить два файла в папке и удалить из названия тот номер, который меньше из двух.

Например, скажем, названия были 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

Общие рекомендации

  1. Проверяйте наличие ошибок: При использовании rm лучше добавлять проверку, чтобы избежать случайного удаления нужных файлов.
  2. Безопасность: Лучше использовать -i с командой rm, чтобы избежать случайного удаления файлов, например, rm -i "$smallest_file".

Следуя этим шагам, вы сможете эффективно сравнивать имена файлов и удалять те из них, которые имеют меньший номер.

Оцените материал
Добавить комментарий

Капча загружается...