Как рекурсивно удалить конечные пробелы всех файлов?

Как вы можете удалить все завершающие пробелы всего проекта? Запуск в корневом каталоге и удаление конечного пробела из всех файлов во всех папках.

Кроме того, я хочу, чтобы иметь возможность изменять файл напрямую, а не просто печатать все на stdout.

Ответ 1

Вот решение OS X >= 10.6 Snow Leopard.

Игнорирует папки .git и .svn и их содержимое. Также он не оставит резервный файл.

find . -not \( -name .svn -prune -o -name .git -prune \) -type f -print0 | xargs -0 sed -i '' -E "s/[[:space:]]*$//"

Ответ 2

Использование:

find . -type f -print0 | xargs -0 perl -pi.bak -e 's/ +$//'

если вы не хотите, чтобы сгенерированные файлы ".bak":

find . -type f -print0 | xargs -0 perl -pi -e 's/ +$//'

как пользователь zsh, вы можете опустить вызов, чтобы найти, и вместо этого использовать:

perl -pi -e 's/ +$//' **/*

Примечание. Чтобы предотвратить уничтожение каталога .git, попробуйте добавить: -not -iwholename '*.git*'.

Ответ 3

В Bash:

find dir -type f -exec sed -i 's/ *$//' '{}' ';'

Примечание. Если вы используете репозиторий .git, попробуйте добавить: -not -iwholename '.git'.

Ответ 4

Два альтернативных подхода, которые также работают с DOS newlines (CR/LF) и выполняют довольно хорошую работу в , избегая двоичных файлов:

Общее решение, которое проверяет, что тип MIME начинается с text/:

while IFS= read -r -d '' -u 9
do
    if [[ "$(file -bs --mime-type -- "$REPLY")" = text/* ]]
    then
        sed -i 's/[ \t]\+\(\r\?\)$/\1/' -- "$REPLY"
    else
        echo "Skipping $REPLY" >&2
    fi
done 9< <(find . -type f -print0)

Git решение для репозитория, которое использует параметр -I git grep для пропуска файлов, которые Git считает двоичным:

git grep -I --name-only -z -e '' | xargs -0 sed -i 's/[ \t]\+\(\r\?\)$/\1/'

Ответ 5

Это работало для меня в OSX 10.5 Leopard, который не использует GNU sed или xargs.

find dir -type f -print0 | xargs -0 sed -i.bak -E "s/[[:space:]]*$//"

Просто будьте осторожны с этим, если у вас есть файлы, которые необходимо исключить (я сделал)!

Вы можете использовать -prune для игнорирования определенных каталогов или файлов. Для файлов Python в репозитории git вы можете использовать что-то вроде:

find dir -not -path '.git' -iname '*.py'

Ответ 6

Для этой задачи была сделана Ack.

Он работает точно так же, как grep, но не знает, чтобы спускаться в такие места, как .svn,.git,.cvs и т.д.

ack --print0 -l '[ \t]+$' | xargs -0 -n1 perl -pi -e 's/[ \t]+$//'

Намного легче, чем прыгать через обручи с помощью find/grep.

Ack доступен через большинство менеджеров пакетов (как ack, так и ack-grep).

Это просто программа Perl, поэтому она также доступна в однофайловой версии, которую вы можете просто загрузить и запустить. Смотрите: Ack Install

Ответ 7

В итоге я не использовал find и не создавал файлы резервных копий.

sed -i '' 's/[[:space:]]*$//g' **/*.*

В зависимости от глубины дерева файлов эта (более короткая версия) может быть достаточной для ваших нужд.

ПРИМЕЧАНИЕ. Это также принимает двоичные файлы, например.

Ответ 8

Вместо того, чтобы исключать файлы, здесь приведено вышеописанное явно белое перечисление файлов на основе расширения файла, которое вы хотите удалить, не стесняясь к сезону:

find . \( -name *.rb -or -name *.html -or -name *.js -or -name *.coffee -or \
-name *.css -or -name *.scss -or -name *.erb -or -name *.yml -or -name *.ru \) \
-print0 | xargs -0 sed -i '' -E "s/[[:space:]]*$//"

Ответ 9

Я закончил работу над этим, это сочетание между версией pojo и adams.

Он очистит оба конечных пробела, а также другую форму конечного пробела, возврат каретки:

find . -not \( -name .svn -prune -o -name .git -prune \) -type f \
  -exec sed -i 's/[:space:]+$//' \{} \;  \
  -exec sed -i 's/\r\n$/\n/' \{} \;

Он не коснется папки .git, если она есть.

Изменить: после комментария было немного безопаснее, не позволяя брать файлы с ".git" или ".svn" в нем. Но будьте осторожны, он коснется двоичных файлов, если у вас их есть. Используйте -iname "*.py" -or -iname "*.php" после -type f, если вы хотите, чтобы он касался, например..py и .php файлы.

Обновление 2: теперь он заменяет все виды пробелов в конце строки (что также означает вкладки)

Ответ 10

Это хорошо работает.. add/remove --include для определенных типов файлов:

egrep -rl ' $' --include *.c *  | xargs sed -i 's/\s\+$//g'

Ответ 11

ex

Попробуйте использовать редактор Ex (часть Vim):

$ ex +'bufdo!%s/\s\+$//e' -cxa **/*.*

Примечание. Для рекурсии (bash4 и zsh) мы используем новую опцию globbing (**/*.*). Включить shopt -s globstar.

Вы можете добавить следующую функцию в .bash_profile:

# Strip trailing whitespaces.
# Usage: trim *.*
# See: https://stackoverflow.com/q/10711051/55075
trim() {
  ex +'bufdo!%s/\s\+$//e' -cxa $*
}

sed

Для esing sed, проверьте: Как удалить конечные пробелы с sed?

find

Найдите следующий script (например, remove_trail_spaces.sh) для удаления конечных пробелов из файлов:

#!/bin/sh
# Script to remove trailing whitespace of all files recursively
# See: https://stackoverflow.com/questions/149057/how-to-remove-trailing-whitespace-of-all-files-recursively

case "$OSTYPE" in
  darwin*) # OSX 10.5 Leopard, which does not use GNU sed or xargs.
    find . -type f -not -iwholename '*.git*' -print0  | xargs -0 sed -i .bak -E "s/[[:space:]]*$//"
    find . -type f -name \*.bak -print0 | xargs -0 rm -v
    ;;
  *)
    find . -type f -not -iwholename '*.git*' -print0 | xargs -0 perl -pi -e 's/ +$//'
esac

Запустите этот script из каталога, который вы хотите отсканировать. В OSX в конце он удалит все файлы, заканчивающиеся на .bak.

Или просто:

find . -type f -name "*.java" -exec perl -p -i -e "s/[ \t]$//g" {} \;

который рекомендуется использовать Spring Стиль кода рамки.

Ответ 12

Ruby:

irb
Dir['lib/**/*.rb'].each{|f| x = File.read(f); File.write(f, x.gsub(/[ \t]+$/,"")) }

Ответ 13

Это то, что работает для меня (Mac OS X 10.8, GNU sed, установленный Homebrew):

find . -path ./vendor -prune -o \
  \( -name '*.java' -o -name '*.xml' -o -name '*.css' \) \
  -exec gsed -i -E 's/\t/    /' \{} \; \
  -exec gsed -i -E 's/[[:space:]]*$//' \{} \; \
  -exec gsed -i -E 's/\r\n/\n/' \{} \;

Удалены конечные пробелы, заменяет вкладки пробелами, заменяет Windows CRLF на Unix \n.

Интересно, что я должен запускать это 3-4 раза, прежде чем все файлы будут исправлены, всеми инструкциями по очистке gsed.

Ответ 14

1) Многие другие ответы используют -E. Я не уверен, почему, как недокументированная BSD-совместимость. -r следует использовать вместо этого.

2) В других ответах используется -i ''. Это должно быть просто -i (или -i'', если оно выбрано), потому что -i имеет суффикс сразу после.

3) Git конкретное решение:

git config --global alias.check-whitespace \
'git diff-tree --check $(git hash-object -t tree /dev/null) HEAD'

git check-whitespace | grep trailing | cut -d: -f1 | uniq -u -z | xargs -0 sed --in-place -e 's/[ \t]+$//'

Первый регистрирует псевдоним Git check-whitespace, в котором перечислены файлы с завершающими пробелами. Второй выполняется sed на них.

Я использую \t, а не [:space:], поскольку я обычно не вижу вертикальных вкладок, фидов форм и неразложимых пробелов. Ваше измерение может отличаться.