Как посмотреть, какие файлы были изменены командой «ed»?

Как посмотреть, какие файлы были изменены командой «ed»?

Я пытаюсь написать скрипт, который гарантирует, что все текстовые файлы заканчиваются символом новой строки.

Когда я запускаю эту команду в определенной папке:

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и вместо этого выводит пользовательское сообщение всякий раз, когда файл фактически был изменен.

Смотрите также:

Связанный контент