2013-12-12 2 views
0

Я пытаюсь использовать unix2dos в группе файлов исходного кода на C++. В принципе, unix2dos преобразует LF в CRLF.для loop/unix2dos для очистки группы файлов с определенным расширением

я мог бы просто сделать следующее, и она делает то, что я хочу:

#!/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 петля кажется немного сложнее в использовании, поскольку пробелы не обрабатываются корректно. Когда имя файла содержит пробел, оболочка пытается неправильно применить unix2dos в разбитой строке.

Как решить проблему?

ответ

1

Просто измените команду unix2dos со следующим (обеспечивается putnamhill верхнего):

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

Затем сделайте свою предыдущую find команду:

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

И вы все готово.

+0

Очень приятно. Если не использовать perl, я думаю, что переопределить псевдоним для 'unix2dos' и применить себя только при необходимости. 'find -exec' - самая естественная форма для меня. –

1
  • Вы не должны обрабатывать вывод команды find в цикле for.

  • Вы должны процитировать ваши переменные должным образом в оболочке.

Попробуйте этот код вместо:

#!/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 

UPDATE: Если вы решили использовать BASH, то вы можете сделать это зацикливание более эффективно. Рассмотрим следующий код:

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

< <(...) синтаксис называется process substitution, что делает выше в то время как цикл в самой текущей оболочки, таким образом, позволяя установить Shel переменные в текущем процессе оболочки и сохранение Разветвляющихся создания суб-оболочки.

+0

Но вы использовали 'while' цикл. То, что я хочу сделать, кажется невозможным с циклом 'for', но я не знаю, почему. –

+0

Спасибо в любом случае, он выполняет эту работу. –

+0

Да, я делаю цикл while, как я показал, является правильным способом, когда имя файла может содержать пробелы или символы новой строки. – anubhava

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

Вы можете проверить с grep, если файл содержит \r и запустить unix2dos условно, так:

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

... где вы вводите ^M, нажав Ctrl + V и Enter. (^M является \r характером)

+0

Пожалуйста, объясните, для чего '^ M'. –

+0

Это символ '\ r' – janos

0

Unix2dos изменит LF на CRLF, но это не изменит CRLF на CRCRLF. Любой существующий разрыв строки DOS останется неизменным. Поэтому самый простой способ сделать то, что вы хотите:

Unix2Dos * .h * .cpp

наилучшими пожеланиями, Эрвин

+0

Я не хочу, чтобы файл был вообще изменен, если он уже в порядке. Элемент управления исходным кодом может обнаружить, что файл был изменен, если вы применяете unix2dos в «чистом файле». –

Смежные вопросы