Atualizei os scripts com base nos exemplos de nome de arquivo que você forneceu em seu comentário:
"Liam sur la moto (VHS) (2001) - Maison 13100.m2ts"
"M&L Plage 1080i (2012) - Camargue 30240.m2ts
Eu criei dois métodos para lidar com essa convenção de nomenclatura.
O primeiro é assumir que, em todos os casos, o ano está entre parênteses. Eu atualizei o script 'primeiro' para refletir esse caso; é simplesmente uma atualização para o padrão regex usado.
regexPat='\(\K[0-9]{4,4}(?=\))'
O segundo script foi atualizado para mostrar um método diferente, em que não podemos ter certeza de que o ano está entre parênteses. Aqui lemos o resultado da avaliação do grep como uma matriz, no caso de haver várias correspondências, e depois fazer uma verificação de sanidade no ano - ou seja, o ano deve ser entre 1970 e 2020; caso contrário, assumimos que não é um ano.
Observe que o comando readarray
(também conhecido como mapfile) está apenas nas versões Bash 4.x + . Na parte inferior é uma versão mais portátil usando apenas read
. Pode ser complicado analisar a saída de find
sem quebras devido a espaços ou caracteres especiais nos nomes dos arquivos. / p>
Script 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. Usando o comando find
para obter uma lista de arquivos e armazená-la em uma matriz usando readarray
.
- Defina o separador de campo para uma nova linha:
IFS=$'\n'
- Use um argumento
-exec
emfind
, que executarábasename
em cada arquivo para obter apenas o nome do arquivo e não o caminho. - A saída
find
é direcionada para uma matriz usando substituição de comando e um < Aqui String ',<<<
e o comandoreadarray
2. Loop na matriz de nomes de arquivos
3. Use grep e regexPat para encontrar o ano incorporado
-
O padrão regex que usei corresponderá a 6 caracteres em uma string quando o primeiro caractere for
(
, seguido por exatamente 4 números[0-9]{4,4}
e fechado por)
no final. -
Para produzir somente os 4 números entre (esperançosamente o ano), o argumento
-P
é dado ao grep para 'Perl Regex' que permite separar caracteres combinados de caracteres capturados (saída), entre outros coisas. - O
/K
fará com que o grep não exiba nada que corresponda antes do/K
no padrão (também conhecido como olhe para frente ). -
Por fim, o
)
de fechamento é removido da saída usando uma não captura semelhante a look-behind semelhante à/K
. Você pode usar basicamente a mesma sintaxe para ambos, o script inferior mostra o método de look-ahead que não usa/K
. -
o
-o
sinalizador informa ao grep para exibir somente a parte correspondente da string capturada, que no nosso caso será um número de 4 dígitos.
O restante do script verifica o número em relação a 1984 e o registra de acordo.
Aqui está outra abordagem mais compacta.
2 coisas para notar aqui
-
find
recebe o argumento-print0
que terminará com o valor nulo saída. - O comando
read
recebe o argumento-d ''
, que informa sua entrada como terminada em null. Uma string nula geralmente é escrita em
em texto simples; no Bash você pode usar''
$'%code%'
ou %code%
Script 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