
Я пытаюсь написать скрипт, который гарантирует, что все текстовые файлы заканчиваются символом новой строки.
Когда я запускаю эту команду в определенной папке:
find . -exec ed -s {} <<< w \;
Я получаю следующий вывод:
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Хорошо, но к каким файлам были добавлены новые строки? Я не вижу никаких изменений в истории Git, так что это неотслеживаемые файлы?
Я также намеренно удалил символ новой строки в конце одного из моих текстовых файлов и ed
не добавляю его обратно...
решение1
Ваша команда немного неверна, так <<<
как перенаправление ввода (строка here-string) прикреплено к find
, а не к ed
.
Немного расширим вашу команду:
find . -type f -exec sh -c '
for pathname do
echo w | ed -s "$pathname"
done' sh {} +
Это повлияет только на обычные файлы в текущем каталоге или где-либо ниже и не будет пытаться редактировать каталоги и другие типы файлов с ed
. Обратите внимание, что двоичные файлы также являются обычными файлами, поэтому мы должны предположить, что вы запускаете это только в каталогах, содержащих текстовые файлы (чтобы не повредить скомпилированные исполняемые файлы, файлы изображений и т. д.)
Для пакетов обычных файлов это вызовет короткий встроенный скрипт оболочки. Скрипт будет перебирать пути, указанные ему в , find
и открывать каждый в ed
, только чтобы немедленно сохранить файл. Это добавляет новую строку к файлам, которые еще не заканчиваются символом новой строки.
Чтобы получить подсказку о том, какие файлы на самом деле изменяются этим, выведите путь перед вызовом ed
. Это выведетвсенайденные пути, но список будет перемежаться сообщениями «Добавлена новая строка» после некоторых из них.
find . -type f -exec sh -c '
for pathname do
printf "%s\n" "$pathname"
echo w | ed -s "$pathname"
done' sh {} +
Чтобы определить, какие файлы были фактически изменены, можно записать данные во временный файл, сравнить его с исходным файлом и заменить исходный файл временным, если есть разница.
find . -type f -exec sh -c '
tmpfile=$(mktemp); trap "rm -f \"$tmpfile\"" EXIT
for pathname do
printf "w %s\n" "$tmpfile" | ed -s "$pathname" 2>/dev/null
if ! cmp -s "$tmpfile" "$pathname"; then
printf "Fixed %s\n" "$pathname"
mv "$tmpfile" "$pathname"
fi
done' sh {} +
Это имеет дополнительное преимущество, поскольку вам не придется обновлять временные метки на файлах, кроме тех, которые вы фактически изменяете.
Это также подавляет сообщение «Добавлена новая строка» ed
и вместо этого выводит пользовательское сообщение всякий раз, когда файл фактически был изменен.
Смотрите также: