我需要从文件名中提取2件事 - 扩展名和数字。
我有一个文件夹" / var / www / html / MyFolder /",此文件夹包含更多文件夹,每个文件夹中都存有一些文件。 该文件具有以下结构:" a_X_mytest.jpg"或" a_X_mytest.png"。 " a _"是修复,并在每个文件夹中相同,我需要" X"和文件扩展名。
我的脚本如下所示:
#!/bin/bash
for dir in /var/www/html/MyFolder/*/
do
dir=${dir%*/}
find "/var/www/html/MyFolder/${dir##*/}/a_*.*" -maxdepth 1 -mindepth 1 -type f
done
这只是我脚本的开头。
我的剧本中有一个错误:
find: `/var/www/html/MyFolder/first/a_*.*': No such file or directory
find: `/var/www/html/MyFolder/sec/a_*.*': No such file or directory
find: `/var/www/html/MyFolder/test/a_*.*': No such file or directory
有人知道错误在哪里吗? 下一步,当上面的行正在工作时,将拆分找到的文件并获得这两部分。
分裂我会用这个:
arrFIRST=(${IN//_/ })
echo ${arrFIRST[1]}
arrEXT=(${IN//./ })
echo ${arrEXT[1]}
有人可以帮我解决问题吗?
答案 0 :(得分:2)
<强> TL; DR:强>
您的脚本可以简化为以下内容:
for file in /var/www/html/MyFolder/*/a_*.*; do
[[ -f $file ]] || continue
[[ "${file##*/}" =~ _(.*)_.*\.(.*)$ ]] &&
x=${BASH_REMATCH[1]} ext=${BASH_REMATCH[2]}
echo "$x"
echo "$ext"
done
/var/www/html/MyFolder/*/a_*.*
在文件夹a_*.*
的任意直接子文件夹(*/
)中找到与/var/www/html/MyFolder
匹配的文件。find
来匹配位于子树的不同级别的文件(但您可能还需要它来满足更复杂的匹配需求)。[[ -f $file ]] || break
确保只考虑文件,如果找不到匹配项,也会有效退出循环。[[ ... =~ ... ]]
使用bash的正则表达式匹配运算符=~
从每个匹配文件(${file##*/}
)的文件名部分中提取感兴趣的标记。正则表达式匹配的结果存储在保留的数组变量"${BASH_REMATCH}"
中,第一个元素包含捕获的第一个带括号的子表达式((...)
- 又称捕获组),依此类推
或者,您可以使用read
数组将匹配的文件名解析为其组件:
IFS='_.' read -ra tokens <<<"${file##*/}"
x="${tokens[0]}"
ext="${tokens[@]: -1}"
至于为什么你尝试过没有工作:
find
不支持将 globs 作为 filename 参数,因此它会逐字地解释"/var/www/html/MyFolder/${dir##*/}/a_*.*"
。-name
或-iname
(不区分大小写的匹配)选项传递(始终引用)文件名模式find "/var/www/html/MyFolder/${dir##*/}" -name 'a_*.*' ...
,类似于@konsolebox' answer。答案 1 :(得分:1)
我不确定所需的复杂性,但也许你想要的是
find /var/www/html/MyFolder/ -mindepth 2 -maxdepth 2 -type f -name 'a_*.*'
因此:
while IFS= read -r FILE; do
# Do something with "$FILE"...
done < <(exec find /var/www/html/MyFolder/ -mindepth 2 -maxdepth 2 -type f -name 'a_*.*')
或者
readarray -t FILES < <(exec find /var/www/html/MyFolder/ -mindepth 2 -maxdepth 2 -type f -name 'a_*.*')
for FILE in "${FILES[@]}"; do
# Do something with "$FILE"...
done