Làm thế nào để loại bỏ khoảng trắng ở cuối của tất cả các tệp một cách đệ quy?


122

Làm thế nào bạn có thể loại bỏ tất cả khoảng trắng cuối của toàn bộ dự án? Bắt đầu từ thư mục gốc và xóa khoảng trắng ở cuối khỏi tất cả các tệp trong tất cả các thư mục.

Ngoài ra, tôi muốn có thể sửa đổi tệp trực tiếp chứ không chỉ in mọi thứ ra stdout.


Ồ, bạn đang tìm kiếm một giải pháp "di động" hay một hệ điều hành cụ thể hơn? Bạn đang sử dụng hệ điều hành nào?
Joe Pineda 29-08

3
Tôi muốn thấy một phiên bản của điều này sẽ hoạt động trên OS X Snow Leopard và sẽ bỏ qua các thư mục .git và .svn.
Trevor Turk

Câu trả lời:


83

Đây là giải pháp cho OS X> = 10.6 Snow Leopard.

Nó bỏ qua các thư mục .git và .svn và nội dung của chúng. Ngoài ra, nó sẽ không để lại một tập tin sao lưu.

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
Bạn có thể làm cho nó nhanh hơn bằng cách sử dụng \+thay thế *trong chuỗi thay thế - Nếu không, nó khớp trên mọi dòng.
l0b0

10
Bạn có thể sử dụng [[: blank:]] để xóa cả tab và dấu cách.
Leif Gruenwoldt

21
Trong Mountain Lion, điều này trả lại sed: RE error: illegal byte sequencecho tôi.
Bryson

12
Đối với những người bạn gặp vấn đề với "chuỗi byte bất hợp pháp": Nhập export LANG=Cvà thử lại
Georg Ledermann

3
Trong OS X 10.9, tôi cũng cần export LC_CTYPE=C như được tìm thấy ở đây: stackoverflow.com/questions/19242275/…
kissgyorgy

31

Sử dụng:

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

nếu bạn không muốn tạo tệp ".bak":

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

với tư cách là người dùng zsh, bạn có thể bỏ qua lệnh gọi để tìm và thay vào đó sử dụng:

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

Lưu ý: Để ngăn chặn phá hủy .gitthư mục, hãy thử thêm: -not -iwholename '*.git*'.


37
Đừng thử điều này trong git repo, vì nó có thể làm hỏng bộ nhớ trong của git.
mgold

11
@mgold Quá muộn, grrr; /
kenorb

3
Để làm rõ, bạn có thể chạy nó bên trong thư mục con của git repo, chỉ là không bên trong bất kỳ thư mục nào chứa (các) git repo dưới dạng con cháu, tức là không bên trong bất kỳ thư mục nào có thư mục .git, bất kể được lồng sâu như thế nào.
Illya Moskvin

Kết hợp câu trả lời này với @ deepwell là để tránh các vấn đề git / svnfind . -not \( -name .svn -prune -o -name .git -prune \) -type f -print0 | xargs -0 perl -pi -e 's/ +$//'
William Denniss

1
Có lẽ có một cách tốt hơn, nhưng tôi đã khôi phục từ việc xử lý git repo với điều này bằng cách sao chép repo trong một thư mục riêng biệt và sau đó thực hiện rsync -rv --exclude=.git repo/ repo2/sau đó các thay đổi cục bộ trong repocũng ở trong (không bị hư hại) repo2.
MatrixManAtYrService

29

Hai cách tiếp cận thay thế cũng hoạt động với các dòng mới DOS (CR / LF) và thực hiện một công việc khá tốt trong việc tránh các tệp nhị phân :

Giải pháp chung kiểm tra xem kiểu MIME có bắt đầu bằng 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)

Giải pháp dành riêng cho kho lưu trữ Git của Mat sử dụng-Itùy chọngit grepbỏ qua các tệp mà Git coi là tệp nhị phân:

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

3
Vì vậy, tôi thực sự thích giải pháp git này. Nó thực sự nên ở trên cùng. Mặc dù vậy, tôi không muốn lưu ký tự xuống dòng. Nhưng tôi thích điều này cho một trong tôi kết hợp trong năm 2010.
odinho - Velmont

Git của tôi than phiền rằng biểu thức -e là trống rỗng, nhưng nó hoạt động tuyệt vời bằng -e '*.'
muirbot

@okor Trong GNU sed, tùy chọn hậu tố -itùy chọn , nhưng trong BSDsed thì không. Nói đúng ra là không cần thiết ở đây, vì vậy tôi sẽ chỉ xóa nó.
l0b0

24

Trong Bash:

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

Lưu ý: Nếu bạn đang sử dụng .gitkho, thử thêm: -not -iwholename '.git'.


Điều này tạo ra các lỗi như thế này cho mọi tệp được tìm thấy. sed: 1: "dir / file.txt": lệnh a mong đợi \ theo sau là văn bản
iamjwc 29/09

Thay thế ';' với \; nên làm việc. (Ngoài ra, các dấu ngoặc kép xung quanh {} là không cần thiết).
agnul

4
Để loại bỏ tất cả khoảng trắng, không chỉ khoảng trắng, bạn nên thay thế ký tự khoảng trắng bằng [: space:] trong biểu thức chính quy sed của bạn.
WMR

Một lưu ý nhỏ khác: Điều này chỉ hoạt động với các phiên bản sed> = 4, các phiên bản nhỏ hơn không hỗ trợ chỉnh sửa tại chỗ.
WMR

1
Này đã phá vỡ git của tôi :(
CrabMan

14

Điều này làm việc cho tôi trong OSX 10.5 Leopard, không sử dụng GNU sed hoặc xargs.

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

Chỉ cần cẩn thận với điều này nếu bạn có tệp cần được loại trừ (tôi đã làm)!

Bạn có thể sử dụng -prune để bỏ qua một số thư mục hoặc tệp nhất định. Đối với các tệp Python trong kho lưu trữ git, bạn có thể sử dụng một số thứ như:

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

Bất kỳ cơ hội nào bạn có thể làm rõ điều này? Tôi muốn một lệnh sẽ xóa khoảng trắng theo sau khỏi tất cả các tệp trong thư mục một cách đệ quy, đồng thời bỏ qua thư mục ".git". Tôi không thể làm theo ví dụ của bạn ...
Trevor Turk

Nếu bạn đang sử dụng tcsh, bạn sẽ cần thay đổi dấu ngoặc kép thành dấu nháy đơn. Nếu không, bạn sẽ nhận được "Tên biến không hợp lệ". lỗi.
Brandon Fosdick

GNU sed cũng tương tự nhưng bạn làm -i.bak hoặc --in-place = .bak, kết thúc bằng một lệnh đầy đủ của find dir -not -path '.git' -iname '*.py' -print0 | xargs -0 sed --in-place=.bak 's/[[:space:]]*$//'. Thay thế dirbằng thư mục được đề cập dưới dạng cấp cao nhất để truy xuất từ ​​đó.
David Gardner

sed -i .bak? Có nên không sed -i.bak(không có khoảng trắng)?
Ondra Žižka

9

Ack được tạo ra cho loại nhiệm vụ này.

Nó hoạt động giống như grep, nhưng không bị rơi vào những nơi như .svn, .git, .cvs, v.v.

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

Dễ dàng hơn nhiều so với nhảy qua vòng với find / grep.

Ack có sẵn thông qua hầu hết các trình quản lý gói (dưới dạng ack hoặc ack-grep ).

Nó chỉ là một chương trình Perl, vì vậy nó cũng có sẵn trong một phiên bản tệp duy nhất mà bạn có thể chỉ cần tải xuống và chạy. Xem: Ack Install


ackthật tuyệt vời. Đã sử dụng nó trong một số năm và có sẵn trong gần như tất cả các gói repo cho hầu hết các bản phân phối.
Felipe Alvarez,

8

ex

Hãy thử sử dụng trình chỉnh sửa Ex (một phần của Vim):

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

Lưu ý: Đối với đệ quy (bash4 & zsh), chúng tôi sử dụng một tùy chọn hình cầu mới ( **/*.*). Bật bởi shopt -s globstar.

Bạn có thể thêm chức năng sau vào .bash_profile:

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

sed

Để sử dụng sed, hãy kiểm tra: Làm thế nào để loại bỏ khoảng trắng ở cuối với sed?

find

Tìm tập lệnh sau (ví dụ remove_trail_spaces.sh) để xóa khoảng trắng ở cuối khỏi tệp:

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

Chạy tập lệnh này từ thư mục mà bạn muốn quét. Trên OSX ở phần cuối, nó sẽ xóa tất cả các tệp có đuôi .bak.

Hoặc chỉ:

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

đó là cách được đề xuất bởi Spring Framework Code Style .


find . -type f -name "*.java" -exec perl -p -i -e "s/[ \t]$//g" {} \;chỉ xóa một dấu cách ở cuối thay vì tất cả.
Karl Richter,

6

Tôi đã không sử dụng tìm và không tạo tệp sao lưu.

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

Tùy thuộc vào độ sâu của cây tệp, bản này (phiên bản ngắn hơn) có thể đủ cho nhu cầu của bạn.

LƯU Ý, ví dụ này cũng có các tệp nhị phân.


Đối với các tệp cụ thể: tìm. -tên '* .rb' | xargs -Tôi {} sed -i '' 's / [[: space:]] * $ // g' {}
Gautam Rege

Bạn không cần tham số '' cho sed; hoặc tôi có thể thiếu một cái gì đó. Tôi đã thử nó trên tất cả các tập tin trong một thư mục nào đó, như thế này: sed -i 's / [[: space:]] * $ // g'. Util / * m
Mircea

6

Thay vì loại trừ các tệp, đây là một biến thể của phần trên, màu trắng liệt kê rõ ràng các tệp, dựa trên phần mở rộng tệp, mà bạn muốn loại bỏ, hãy thoải mái thêm gia vị để thưởng thức:

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

Đối với điều này để làm việc cho tôi rằng tôi cần phải thêm dấu ngoặc kép:-name "*.rb*"
haroldcarr

5

Cuối cùng tôi đã chạy cái này, đây là sự kết hợp giữa phiên bản pojo và adams.

Nó sẽ làm sạch cả khoảng trắng ở cuối và cũng là một dạng khác của khoảng trắng ở cuối, dấu xuống dòng:

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

Nó sẽ không chạm vào thư mục .git nếu có.

Chỉnh sửa : Làm cho nó an toàn hơn một chút sau khi nhận xét, không cho phép lấy các tệp có ".git" hoặc ".svn" trong đó. Nhưng hãy cẩn thận, nó sẽ chạm vào các tệp nhị phân nếu bạn có một số. Sử dụng -iname "*.py" -or -iname "*.php"sau -type fnếu bạn chỉ muốn nó chạm vào, ví dụ: .py và .php-files.

Cập nhật 2 : Nó hiện thay thế tất cả các loại khoảng trắng ở cuối dòng (có nghĩa là cả các tab)


4
Tôi không biết chuyện gì đang xảy ra, nhưng điều này hoàn toàn làm hỏng git repo của tôi và làm rối tung hình ảnh của tôi. HÃY CẨN THẬN HƠN MÌNH NHÉ!
mattalxndr

Có, nó sẽ làm hỏng các tệp nhị phân. Tuy nhiên, nó hoàn toàn không nên chạm vào git repo của bạn, vì nó bỏ qua bất cứ thứ gì nằm bên trong thư mục .git-. Nhưng có lẽ chỉ khi bạn ở trong cùng một thư mục.
odinho - Velmont

4

Điều này hoạt động tốt .. thêm / xóa - bao gồm cho các loại tệp cụ thể:

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


3

Tôi sử dụng biểu thức chính quy. 4 bước:

  1. Mở thư mục gốc trong trình soạn thảo của bạn (Tôi sử dụng Visual Studio Code).
  2. Nhấn vào biểu tượng Tìm kiếm ở bên trái và bật chế độ biểu thức chính quy.
  3. Nhập "+ \ n" vào thanh Tìm kiếm và "\ n" vào thanh Thay thế.
  4. Nhấp vào "Thay thế Tất cả".

Thao tác này sẽ xóa tất cả các khoảng trắng ở cuối mỗi dòng trong tất cả các tệp. Và bạn có thể loại trừ một số tệp không phù hợp với nhu cầu này.


2

1) Nhiều câu trả lời khác sử dụng -E. Tôi không chắc tại sao, vì đó là tùy chọn tương thích BSD không có tài liệu . -rnên được sử dụng thay thế.

2) Các câu trả lời khác sử dụng -i ''. Đó chỉ nên là -i(hoặc -i''nếu được ưu tiên), vì -icó hậu tố ngay sau.

3) Giải pháp cụ thể cho 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]+$//'

Cái đầu tiên đăng ký một bí danh git check-whitespaceliệt kê các tệp có khoảng trắng ở cuối. Cái thứ hai chạy sedtrên chúng.

Tôi chỉ sử dụng \tchứ không phải [:space:]vì tôi thường không thấy các tab dọc, nguồn cấp dữ liệu biểu mẫu và không gian không thể ngắt. Số đo của bạn có thể khác nhau.


1

Đây là những gì phù hợp với tôi (Mac OS X 10.8, GNU sed được cài đặt bởi 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/' \{} \;

Đã xóa dấu cách ở cuối, thay thế tab bằng dấu cách, thay thế Windows CRLF bằng Unix \n.

Điều thú vị là tôi phải chạy điều này 3-4 lần trước khi tất cả các tệp được sửa bằng tất cả các gsedhướng dẫn làm sạch .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.