2011-06-30 34 views
1

似乎无法破解这一个。Bash排除点短划线前缀

我有一个bash脚本来搜索一个文件夹并排除某些文件类型。

list=`find . -type f ! \(-name "*data.php" -o -name "*.log" -o -iname "._*" -o -path "*patch" \)` 

我想排除以dot-dash ._开头的文件,但以上只是拒绝工作。

这里的一些剧本,但我仍然得到与开始复制文件与._

O/S是CentOS的5.3

list=`find . -type f ! \(-name "*data.php" -o -name "*.log" -o -iname "._*" -o -path "*patch" \)` 
    for a in $list; do 
     if [ ! -f "$OLDFOL$a" ]; then 
      cp --preserve=all --parents $a $UPGFOL 
      continue 
     fi 
     diff $a "$OLDFOL$a" > /dev/null 
     if [[ "$?" == "1" ]]; then 
      # exists & different so copy 
      cp --preserve=all --parents $a $UPGFOL 
     fi 
    done 
+0

适合我(在GNU find版本4.1.20) – dogbane

+3

你的意思是点下划线? –

+0

甚至可以在WinXP/Cygwin上使用findutils 4.5.9。那么,它不起作用是什么? – carlpett

回答

2

首先 - 不要那样做。

files="`find ...`" 

按空白进行分割的名字,这意味着Some File变成了两个文件,SomeFile。即使在换行符上分割也是不安全的,因为有效的UNIX文件名可以包含$'\n'(除/之外的任何字符,并且null在UNIX文件名中有效)。相反...

getfiles() { 
    find . -type f '!' '(' \ 
    -name '*data.php' -o \ 
    -name '*.log' -o \ 
    -iname "._*" -o \ 
    -path "*patch" ')' \ 
    -print0 
} 
while IFS= read -r -d '' file; do 
    if [[ ! -e $orig_dir/$file ]] ; then 
    cp --preserve=all --parents "$file" "$dest_dir" 
    continue 
    fi 
    if ! cmp -q "$file" "$orig_dir/$file" ; then 
    cp --preserve=all --parents "$file" "$dest_dir" 
    fi 
done < <(getfiles) 

上述操作权的一些事情:

  • 这是对包含空格或换行符的文件名是安全的。
  • 它使用cmp -q而不是diffcmp在进行更改时立即退出,而不需要计算两个文件之间的增量,因此速度更快。

BashFAQ #1UsingFindBashPitfalls #1了解一些这和原来的差异。

另外 - 我已验证,这正确排除文件名以._开头 - 但原始版本也是如此。也许真的想要的是排除文件名匹配*._*而不是._*