我需要从文件名中提取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
有人知道错误在哪里吗? 下一步,当上面的行正在工作,是分裂find的文件,并得到这两个部分。
要分裂我会使用这个:
arrFIRST=(${IN//_/ }) echo ${arrFIRST[1]} arrEXT=(${IN//./ }) echo ${arrEXT[1]}
有人可以帮我解决我的问题吗?
TL;博士:
您的脚本可以简化为以下内容:
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/*/a_*.*
_ a_*.*
找到匹配a_*.*
文件a_*.*
在文件夹/var/www/html/MyFolder
的( */
)的任何直接子文件夹中。 find
匹配位于子树不同层次上的文件(但是你也可能需要它来满足更复杂的匹配需求)。 [[ -f $file ]] || break
[[ -f $file ]] || break
保证只有文件被考虑,并且如果找到NO匹配,也有效地退出循环。 [[ ... =~ ... ]]
使用bash的正则表达式匹配运算符=~
,从每个匹配文件( ${file##*/}
)的文件名部分中提取感兴趣的令牌。 正则表达式匹配的结果存储在保留数组变量"${BASH_REMATCH}"
,第一个元素包含第一个加括号的子表达式( (...)
– 又名捕获组)捕获的内容等等。
或者,您可以使用数组read
匹配的文件名到其组件中:
IFS='_.' read -ra tokens <<<"${file##*/}" x="${tokens[0]}" ext="${tokens[@]: -1}"
至于你为什么试了没有工作 :
find
不支持globs作为文件名参数,所以它直接解释"/var/www/html/MyFolder/${dir##*/}/a_*.*"
。 -name
或-iname
(不区分大小写的匹配)选项传递(总是引用) find "/var/www/html/MyFolder/${dir##*/}" -name 'a_*.*' ...
– name'a find "/var/www/html/MyFolder/${dir##*/}" -name 'a_*.*' ...
,类似于@konsolebox的答案 。 我不确定所需的复杂性,但也许你想要的是
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