我正在尝试通过 Bash 脚本根据模式移动文件。
我使用 find 来选择我的所有摄像机文件并将结果保存到 TXT 文件中。
我的每个摄像机文件都包含年份位置,我想使用 Grep 或其他东西来查找此字符串(4 位数字的年份,即 1984)并比较此字符串以将文件移动到不同的文件夹中,如果文件在 1984 年之后,那么我的文件必须进入文件夹“Marie”,如果文件在 1984 年之前或等同于 1984 年,则必须进入文件夹“Marie_Liam”。
我尝试了几种方法,使用 Grep 并在 read -r line 时进行尝试,但是当我比较找到的字符串(年份)时,我的脚本每次都会返回 1984 年之后的内容...
这是我的不同尝试:
我已经尝试了几件类似的事情(需要很多次尝试,而不仅仅是一个脚本):
基本脚本:
#!/bin/bash
find /home/CamFiles/ -name "*.m2ts"
尝试1:
TestScriptResultFile="/home/Dio/CamCorderFindResult.file"
do
if [ grep -e " 1984 " "$in" ];
then
echo "Voici un film qui est avant 1984 $FindMovie"
else
echo "Voici un film qui est de 1984 : $FindMovie"
fi;
done
-- 再试一次 --
while IFS= read -r line; do
if [[ /bin/grep -E "[1][9][8][4]" "$MyLine" != 0 ]] ;
then
echo "Ok"
fi
done < "$TestScriptResultFile"
while read line; do
if echo "$line" | grep -q "[1][9][8][4]"; then echo "$line"; fi
Found=$(echo "$line" | grep -q "[1][9][0-8][0-4]")
if [[ " $Found " <= 1984 ]]; then echo "$line"; fi
done < "$TestScriptResultFile"
exit 0
-- 再试一次 --
while read MyLine
do
if grep -E "$MyPattern" "$MyLine"
then
echo "tourne apres 1984 : $MyLine"
else
echo "Tourne avant 1984 : $MyLine"
fi
done < "$TestScriptResultFile"
感谢您的帮助。
此致。
答案1
我根据您在评论中提供的文件名示例更新了脚本:
"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
通过使用命令替换和一个'这里字符串'以及<<<
命令readarray
2. 循环遍历文件名数组
3. 使用 grep 和 regexPat 查找嵌入的年份
(
当第一个字符是,后面跟着 4 个数字[0-9]{4,4}
,最后以 结尾)
时,我使用的正则表达式模式将匹配字符串中的 6 个字符。为了仅输出中间的 4 个数字(希望是年份),
-P
为 grep 提供了“Perl Regex”的参数,它允许将匹配的字符与捕获的(输出)字符分开,等等。这
/K
将导致 grep 不输出/K
模式中与 之前匹配的任何内容(也称为展望)。)
最后,使用类似于的后视非捕获从输出中删除结束/K
。您可以使用基本相同的语法,底部脚本显示了不使用的前视方法/K
。该
-o
标志告诉 grep 仅输出捕获的、匹配的字符串部分,在我们的例子中是一个 4 位数字。
脚本的其余部分根据 1984 检查该数字并进行相应的记录。
这是另一种更紧凑的方法。
这里有两件事需要注意
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