Я обновил сценарии на основе примеров имен файлов, которые вы предоставили в своем комментарии:
"Liam sur la moto (VHS) (2001) - Maison 13100.m2ts"
"M&L Plage 1080i (2012) - Camargue 30240.m2ts
Я придумал два метода для обработки этого соглашения об именах.
Первый заключается в предположении, что в каждом случае год заключен в круглые скобки. Я обновил «первый» скрипт, чтобы отразить этот случай; это просто обновление шаблона регулярных выражений, которое используется.
regexPat='\(\K[0-9]{4,4}(?=\))'
Второй скрипт был обновлен, чтобы показать другой метод, где мы не можем быть уверены, что год заключен в круглые скобки. Здесь мы зачитываем результат оценки grep в виде массива в случае множественных совпадений, а затем выполняем проверку работоспособности года - т.е. год должен быть между 1970 и 2020 годами; в противном случае мы предполагаем, что это не год.
Обратите внимание, что команда readarray
(она же mapfile) есть только в версиях Bash 4.x+. Внизу - более портативная версия с использованием только что read
. Может быть сложно проанализировать вывод команды find
без проблем из-за пробелов или специальных символов в именах файлов.
Сценарий 1
#!/bin/bash
# Create test files
touch abcd\({2001,1985,1984,1931}\)efgh.m2ts
touch abcd{24001,198a5,19b84,1912331,1293}.m2ts
touch "abcd 1232 adffd.m2ts"
touch "Liam sur la moto (VHS) (2001) - Maison 13100.m2ts"
touch "M&L Plage 1080i (2012) - Camargue 30240.m2ts"
TestScriptResultFile="./CamCorderFindResult.file"
touch $TestScriptResultFile
regexPat='\(\K[0-9]{4,4}(?=\))'
readarray fileList <<<"$(IFS="\n" ; find . -name "*.m2ts" -exec basename {} \;)"
for i in "${fileList[@]}"; do
echo "Processing File: $i"
if year=$(grep -oP "$regexPat" <<<"$i"); then
if [ "$year" -le 1984 ]; then
echo "1984 or earlier: $i" >> "$TestScriptResultFile"
else
echo "After 1984: $i" >> "$TestScriptResultFile"
fi
else
echo "No valid year found in file $i"
fi
done
1. Использование команды find
для получения списка файлов и сохранения его в массиве с использованием readarray
.
- Установите разделитель полей на новую строку:
IFS=$'\n'
- Используйте аргумент
-exec
в find
который будет запускать basename
для каждого файла, чтобы получить только имя файла, а не путь.
- Выходные данные
find
направляются в массив с помощью подстановки команд и команд ' Here String', <<<
и команда readarray
2. Цикл в массиве имен файлов
3. Используйте grep и regexPat, чтобы найти внедренный год
Шаблон регулярного выражения, который я использовал, будет соответствовать 6 символам в строке, когда первый символ представляет собой (
последующим ровно 4 числами [0-9]{4,4}
и закрытый символом a )
в конце.
Чтобы вывести только 4 числа между (надеюсь, год), аргумент -P
задается grep для 'Perl Regex', который позволяет отделить совпадающие символы от захваченных (выходных) символов, среди прочего.
/K
заставит grep не выводить ничего, что совпадает с /K
в шаблоне (так называемый прогноз).
Наконец, закрывающее значение )
удаляется из выходных данных с помощью скрытого отсутствия захвата, подобного /K
Вы можете использовать в основном один и тот же синтаксис для обоих, нижний скрипт показывает метод упреждения, который не использует /K
флаг -o
указывает grep выводить только захваченную, совпадающую часть строки, которая в нашем случае будет четырехзначным числом.
Остальная часть скрипта проверяет число по отношению к 1984 и записывает его соответствующим образом.
Вот еще один более компактный подход.
2 вещи, чтобы отметить здесь
find
получает аргумент -print0
который завершает вывод.
- Команде
read
присваивается аргумент -d ''
, который сообщает, что ее ввод завершается нулем. Нулевая строка обычно пишется \0
в виде простого текста; в Bash вы можете использовать ''
или $'\0'
Сценарий 2
#!/bin/bash
TestScriptResultFile="./CamCorderFindResult.file"
touch $TestScriptResultFile
regexPat='(?<=[^0-9])[0-9]{4,4}(?=[^0-9])'
find . -name "*.m2ts" -print0 | while IFS= read -r -d '' k; do
i="$(basename "$k")"
echo "Processing File: $i"
if year=($(grep -oP "$regexPat" <<<"$i")); then
for yr in "${year[@]}"; do
if [ "$yr" -lt 1970 ] || [ "$yr" -gt 2020 ]; then
echo " x Out of range year ($yr) parsed from $i"
else
echo " o Found year $yr"
if [ "$yr" -le 1984 ]; then
echo "1984 or earlier: $i" >> "$TestScriptResultFile"
else
echo "After 1984: $i" >> "$TestScriptResultFile"
fi
fi
done
else
echo " x No valid year found in file $i"
fi
done