모든 파일의 후행 공백을 재귀 적으로 제거하는 방법은 무엇입니까?


122

전체 프로젝트의 후행 공백을 모두 제거하려면 어떻게해야합니까? 루트 디렉토리에서 시작하여 모든 폴더의 모든 파일에서 후행 공백을 제거합니다.

또한 모든 것을 stdout에 인쇄하는 것이 아니라 파일을 직접 수정할 수 있기를 원합니다.


아, "휴대용"솔루션을 찾고 계십니까? 아니면 OS 별 솔루션을 찾고 계십니까? 어떤 OS를 사용하고 있습니까?
Joe Pineda

3
OS X Snow Leopard에서 작동하고 .git 및 .svn 폴더를 무시하는 버전을보고 싶습니다.
Trevor Turk

답변:


83

다음은 OS X> = 10.6 Snow Leopard 솔루션입니다.

.git 및 .svn 폴더 와 그 내용을 무시합니다 . 또한 백업 파일을 남기지 않습니다.

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

10
대체 문자열 \+대신 사용하여 더 빠르게 만들 수 있습니다. *그렇지 않으면 모든 단일 행에서 일치합니다.
l0b0

10
[[: blank :]]를 사용하여 탭과 공백을 모두 제거 할 수 있습니다.
Leif Gruenwoldt

21
Mountain Lion에서 이것은 sed: RE error: illegal byte sequence나를 위해 돌아옵니다 .
Bryson 2013

12
당신이 "불법 바이트 순서"로 문제가의 사람들을 위해 : 입력 export LANG=C하고 다시 시도
게오르그 Ledermann을

3
OS X 10.9에서는 다음 export LC_CTYPE=C 과 같이 필요 합니다. stackoverflow.com/questions/19242275/…
kissgyorgy

31

사용하다:

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*'..


37
git 저장소에서 시도하지 마십시오. git의 내부 저장소가 손상 될 수 있습니다.
mgold

11
@mgold 너무 늦었, 유감스럽게도 /
kenorb

3
명확히하기 위해, git repo (s)를 자손으로 포함하는 폴더 내부가 아니라 git repo의 하위 폴더 내에서 실행하는 것이 .git좋습니다. 즉 , 아무리 깊게 중첩되어 있더라도 디렉토리 가있는 폴더 내부가 아닙니다 .
Illya Moskvin 2016

@ deepwell로이 답변을 결합하면 자식 / svn의 문제를 방지 할 수있어find . -not \( -name .svn -prune -o -name .git -prune \) -type f -print0 | xargs -0 perl -pi -e 's/ +$//'
윌리엄 Denniss

1
더 좋은 방법이있을 수 있지만, 별도의 폴더에 저장소를 복제 한 다음 rsync -rv --exclude=.git repo/ repo2/로컬 변경 사항 repo도 (손상되지 않음)에 포함 되어이 작업을 통해 git 저장소를 망가 뜨리지 않고 복구했습니다 repo2.
MatrixManAtYrService

29

DOS 줄 바꿈 (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옵션을 사용하는 Mat의 Git 저장소 별 솔루션git grep :

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

3
그래서 저는이 자식 솔루션을 정말 좋아합니다. 정말 맨 위에 있어야합니다. 그래도 캐리지 리턴을 저장하고 싶지 않습니다. 하지만 2010 년에 결합 된 하나의 I이 선호
odinho - Velmont

내 자식은 -e 표현식이 비어 있다고 불평하지만 -e '. *'를 사용하면 잘 작동합니다.
muirbot

@okor GNU sed에서 접미사 옵션 -i선택 사항 이지만 BSDsed 에서는 그렇지 않습니다. 어쨌든 여기서는 엄격히 말해서 필요하지 않으므로 제거하겠습니다.
l0b0 2014 년

24

Bash에서 :

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

참고 : .git저장소를 사용하는 경우 추가해보십시오 -not -iwholename '.git'..


이것은 발견 된 모든 파일에 대해 이와 같은 오류를 생성합니다. sed : 1 : "dir / file.txt": 명령 a는 \ 다음에 텍스트를 기대합니다
iamjwc

';'바꾸기 \; 작동합니다. (또한 {} 주위의 따옴표는 꼭 필요하지 않습니다).
agnul

4
공백뿐만 아니라 모든 공백을 제거하려면 sed 정규식에서 공백 문자를 [: space :]로 바꿔야합니다.
WMR

또 다른 참고 사항 : 이것은 sed 버전> = 4에서만 작동하며 더 작은 버전은 인플레 이스 편집을 지원하지 않습니다.
WMR

1
이것은 내 자식 :(
CrabMan

14

이것은 GNU sed 또는 xargs를 사용하지 않는 OSX 10.5 Leopard에서 저에게 효과적이었습니다.

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

제외해야 할 파일이 있으면 조심하십시오 (내가했습니다)!

-prune을 사용하여 특정 디렉토리 나 파일을 무시할 수 있습니다. git 저장소의 Python 파일의 경우 다음과 같이 사용할 수 있습니다.

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

이것을 명확히 할 수 있습니까? ".git"디렉토리를 무시하면서 디렉토리의 모든 파일에서 후행 공백을 재귀 적으로 제거하는 명령을 원합니다. 나는 당신의 예를 잘 따를 수 없습니다 ...
Trevor Turk

tcsh를 사용하는 경우 큰 따옴표를 작은 따옴표로 변경해야합니다. 그렇지 않으면 "잘못된 변수 이름"이 표시됩니다. 오류.
Brandon Fosdick

GNU sed는 비슷하지만 -i.bak 또는 --in-place = .bak를 수행하여 find dir -not -path '.git' -iname '*.py' -print0 | xargs -0 sed --in-place=.bak 's/[[:space:]]*$//'. dir재귀 할 최상위 레벨로 문제의 디렉토리로 바꿉니다 .
David Gardner

sed -i .bak? sed -i.bak(공백없이) 해야하지 않습니까?
Ondra Žižka

9

이러한 종류의 작업을 위해 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


ack멋진. 수년 동안 사용했으며 대부분의 배포판에서 거의 모든 패키지 저장소에서 사용할 수 있습니다.
Felipe Alvarez

8

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

사용을 위해 sed 하려면 sed로 후행 공백을 제거하는 방법을 확인하십시오.

find

remove_trail_spaces.sh파일에서 후행 공백을 제거하기위한 다음 스크립트 (예 :)를 찾으십시오 .

#!/bin/sh
# Script to remove trailing whitespace of all files recursively
# See: /programming/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

스캔하려는 디렉토리에서이 스크립트를 실행하십시오. 마지막에 OSX에서는 .bak.

아니면 그냥 :

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

Spring Framework Code Style에서 권장하는 방식 입니다.


find . -type f -name "*.java" -exec perl -p -i -e "s/[ \t]$//g" {} \;모두가 아니라 하나의 후행 공백 만 제거합니다.
Karl Richter

6

나는 찾기를 사용하지 않고 백업 파일을 만들지 않았습니다.

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

파일 트리의 깊이에 따라이 정도 (짧은 버전)이면 충분할 수 있습니다.

참고 이것은 예를 들어 바이너리 파일도 사용합니다.


특정 파일의 경우 :. -이름 '* .rb'| xargs -I {} sed -i '' 's / [[: space :]] * $ // g'{}
Gautam Rege

sed에는 ''매개 변수가 필요하지 않습니다. 아니면 뭔가 빠졌을 수도 있습니다. 다음과 같이 주어진 디렉토리의 모든 파일에 대해 시도했습니다. sed -i 's / [[: space :]] * $ // g'util / *. m
Mircea

6

파일을 제외하는 대신 파일 확장자에 따라 파일을 명시 적으로 화이트리스트에 나열한 위의 변형이 있습니다. 자유롭게 맛볼 수 있습니다.

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:]]*$//"

이것이 나를 위해 작동하려면 따옴표를 추가해야했습니다.-name "*.rb*"
haroldcarr

5

나는 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"이 포함 된 파일을 가져 오지 못하도록 주석 뒤에 조금 더 안전하게 만들었습니다. 그러나 일부가 있다면 바이너리 파일 건드릴 것 입니다 . .py 및 .php 파일과 같은 터치 만 원할 경우 -iname "*.py" -or -iname "*.php"after를 사용하십시오 -type f.

업데이트 2 : 이제 줄 끝에서 모든 종류의 공백을 대체합니다 (탭도 의미 함).


4
나는 무슨 일이 일어나고 있는지 모르겠지만 이것은 내 자식 저장소를 완전히 망치고 내 이미지를 엉망으로 만들었습니다. 사람들, 내가 그랬던 것보다 더 조심하세요!
mattalxndr 2011

예, 바이너리 파일을 망칠 것입니다. 그러나 .git 폴더 안에있는 모든 것을 건너 뛰기 때문에 git 저장소를 전혀 건드리지 않아야합니다. 하지만 같은 폴더에있는 경우에만 가능합니다.
odinho-Velmont

4

이것은 잘 작동합니다 .. 특정 파일 유형에 대해 --include 추가 / 제거 :

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

4

루비:

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

3

정규식을 사용합니다. 4 단계 :

  1. 편집기에서 루트 폴더를 엽니 다 (Visual Studio Code 사용).
  2. 왼쪽의 검색 아이콘을 누르고 정규식 모드를 활성화합니다.
  3. 검색 창에 "+ \ n"을 입력하고 바꾸기 창에 "\ n"을 입력합니다.
  4. "모두 바꾸기"를 클릭합니다.

이렇게하면 모든 파일의 각 줄 끝에있는 모든 후행 공백이 제거됩니다. 그리고 이러한 요구에 맞지 않는 일부 파일을 제외 할 수 있습니다.


2

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]+$//'

첫 번째 check-whitespace는 후행 공백이있는 파일을 나열 하는 git 별칭 을 등록합니다 . 두 번째는 sed그들 위에서 실행 됩니다.

일반적으로 세로 탭, 양식 피드 및 깨지지 않는 공백이 표시되지 않으므로 \t대신 사용 [:space:]합니다. 측정은 다를 수 있습니다.


1

이것은 나를 위해 작동하는 것입니다 (Mac OS X 10.8, Homebrew가 설치 한 GNU sed).

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.

흥미로운 점은 모든 정리 gsed지침에 따라 모든 파일이 수정되기 전에이 작업을 3-4 번 실행해야한다는 것 입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.