for loop / unix2dos清除一组具有特定扩展名的文件

时间:2013-12-12 16:41:23

标签: shell loops newline dos2unix

我正在尝试在一组C ++源代码文件上使用unix2dos。基本上,unix2dos将LF转换为CRLF。

我可以简单地执行以下操作,它可以完成我想要的操作:

#!/bin/sh
find . -type f \( -name "*.h" -o -name "*.cpp" \) -exec unix2dos {}\;

但如果文件已经有CRLF行,我不希望修改该文件。 这就是我必须修改脚本的原因。

#!/bin/sh
for i in `find . -type f \( -name "*.h" -o -name "*.cpp" \)` 
do
  LINE=`file $i | grep CRLF`
  if [ $? -eq 1 ]
  then
    unix2dos $i
  fi
done

使用for循环似乎有点棘手,因为没有正确处理空格。当文件名包含空格时,shell会尝试在拆分的字符串上错误地应用unix2dos。

如何解决问题?

5 个答案:

答案 0 :(得分:3)

您可以使用以下perl,它应该保持CRLF文件不变:

#!/bin/sh
find . -type f \( -name "*.h" -o -name "*.cpp" \) -exec perl -pi -e 's/([^\r])\n/$1\r\n/' "{}"\;

它将在任何不在CR之前的LF之前插入CR。

答案 1 :(得分:1)

  • 您不应在for循环中处理find命令的输出。

  • 您需要在shell中正确引用变量。

请尝试使用此代码:

#!/bin/sh
find . -type f \( -name "*.h" -o -name "*.cpp" \) | while read i
do
  LINE=`file "$i" | grep -c CRLF`
  if [ $LINE -eq 0 ]
  then
    unix2dos "$i"
  fi
done

更新:如果您决定使用BASH,那么您可以更有效地执行此循环。请考虑以下代码:

#!/bin/bash
while read file
do
  grep -q $'\r'"$" "$file" && unix2dos "$file"
done < <(find . -type f \( -name "*.h" -o -name "*.cpp" \))

< <(...)语法称为process substitution,它在当前shell本身的while循环中生成,因此允许您在当前shell进程中设置shel变量并保存子shell创建的分支。

答案 2 :(得分:1)

如果文件包含grep并且有条件地运行\r,您可以使用unix2dos查看,如下所示:

find . -type f \( -name "*.h" -o -name "*.cpp" \) -exec sh -c 'grep -q ^M "{}" && dos2unix "{}"' \;

...按Control-V和Enter键输入^M。 (^M\r个字符)

答案 3 :(得分:1)

只需使用以下内容(由putnamhill upper提供)更改unix2dos命令:

`perl -wpi -e 's/([^\r])\n/$1\r\n/g' $1`;

然后执行上一个find命令:

#!/bin/sh
find . -type f \( -name "*.h" -o -name "*.cpp" \) -exec unix2dos {}\;

你们已经定下来了。

答案 4 :(得分:0)

Unix2dos会将LF更改为CRLF,但不会将CRLF更改为CRCRLF。任何现有的DOS换行符都将保持不变。所以做你想做的最简单的方法是:

unix2dos * .h * .cpp

最好的问候, 欧文