根据正则表达式检查/移动文件

时间:2013-08-20 20:58:41

标签: regex shell osx-mountain-lion

我试图在mac上编写一个shell脚本来移动原始相机文件。这些文件需要非常具体地命名。我有正则表达式检查文件名,我只是没有运气使其正常工作。正确工作是在特定文件夹中查找包含原始文件的文件夹名称并获取文件列表。

我也试图错误检查。我一直在尝试使用if语句检查文件名。

我需要帮助编写if语句来检查文件是否正确命名。

我非常感谢任何帮助,因为我完全陷入了困境。

这是我到目前为止所拥有的:

#!/bin/bash

product="^[A-Z0-9]{2}\w[A-Z0-9]{6,7}\w[A-Z]{1}\.(EIP)"

#folder of files to check
folder_files="$(ls -d *)"

#just get a list of everything .EIP
FILES_LIST="$(ls *.EIP)"

for file in $FILES_LIST; do
#something with $file

echo $file

#where im having the trouble 
If (grep or find based on $product)
then

    #move files, create log

else

    #move files to an error folder for renaming

fi

done
exit 0

2 个答案:

答案 0 :(得分:2)

大括号是扩展常规扩展(ERE)语法的一部分, 不是基本的正则表达式(BRE)语法所以我们需要使用“egrep”。我也冒昧地从你的正则表达式中删除括号,因为我发现你正在查找以.EIP结尾的文件,所以这给我们留下了:

product="^[A-Z0-9]{2}\w[A-Z0-9]{6,7}\w[A-Z]{1}\.EIP"

我们还需要更改$IFS变量,因为FOR循环使用它来确定字段分隔符。默认情况下,字段分隔符设置为空格字符,这对于字符串分隔符可以是字符串的一部分的字符串(即文件名包含空格)不起作用。我们将IFS的当前值存储到变量中,然后设置IFS:

SAVEIFS=$IFS
IFS=$(echo -en "\n\b")

当我们完成后,我们将把IFS恢复到原始值:

IFS=$SAVEIFS

现在我们将文件名管道传输到egrep并使用我们的正则表达式进行过滤,同时将stdoutstderr重定向到/dev/null。如果我们的egrep返回匹配项,$?变量将告诉我们。

echo $file | egrep $product &>/dev/null
if [ $? -eq 0 ]; then 
  echo "$file - acceptable"
else 
  echo "$file - not acceptable"
fi

以下是完整脚本的样子(在山狮上测试):

#!/bin/bash 

product="^[A-Z0-9]{2}\w[A-Z0-9]{6,7}\w[A-Z]{1}\.EIP"

FILES_LIST="$(ls *.EIP)"

SAVEIFS=$IFS
IFS=$(echo -en "\n\b")

for file in $FILES_LIST; do
  echo $file | egrep $product &>/dev/null
  if [ $? -eq 0 ]; then 
    echo "$file - acceptable"
    #move files, create log
  else 
    echo "$file - not acceptable"
    #move files to an error folder for renaming
  fi
done

IFS=$SAVEIFS

exit 0

请注意,您可以使用多个if语句块并在最后只有一个else条件来检查是否符合 N 命名约定,如下所示:

for file in $FILES_LIST; do

  echo $file | egrep $regex1 &>/dev/null
  if [ $? -eq 0 ]; then 
    echo "$file - accepted by regex1"
    #move files, create log
    continue
  fi

  echo $file | egrep $regex2 &>/dev/null
  if [ $? -eq 0 ]; then 
    echo "$file - accepted by regex2"
    #move files, create log
    continue
  fi

  echo $file | egrep $regexN &>/dev/null
  if [ $? -eq 0 ]; then 
    echo "$file - accepted by regexN"
    #move files, create log
  else 
    echo "$file - not acceptable"
    #move files to an error folder for renaming
  fi
done

注意continue的使用,因为它恢复for循环的迭代,允许每个文件只采取一个动作(考虑符合多于1个命名约定的文件名)< / p>

答案 1 :(得分:1)

我不确定macosx是否使用gnu find,但我敢打赌它确实如此。

find . -regextype posix-egrep -ireg ${myregex} -print

要匹配的文件名包含整个路径,因此您需要使用^。/启动正则表达式并以$

结尾

而不是if,我宁愿将整个事情写成两个xargs。

# first move the good stuff to its destination
find . -type f -regextype posix-egrep -ireg ${myregex} -print0 | xargs -I{} -0 mv {} ../good-dir/
# anything remaining is bad
find . -type f -print0 | xargs -I{} -0 sh -c 'echo "bad file name: {}" > /var/log/whatever.log; mv {} ../bad-dir/'