如何递归删除所有文件的结尾空格?


122

如何删除整个项目的所有尾随空白?从根目录开始,并从所有文件夹中的所有文件中删除尾随空格。

另外,我希望能够直接修改文件,而不仅仅是将所有内容打印到stdout。


哦,您是在寻找“便携式”解决方案,还是更特定于操作系统的解决方案?您正在使用什么操作系统?
乔·皮内达

3
我很想看到一个可以在OS X Snow Leopard上运行的版本,并且可以忽略.git和.svn文件夹。
Trevor Turk 2010年

Answers:


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 2012年

10
您可以使用[[:blank:]]删除制表符和空格。
Leif Gruenwoldt 2012年

21
在《山狮》中,这sed: RE error: illegal byte sequence为我带来了回报。
布赖森

12
对于那些遇到“非法字节序列”问题的人:输入export LANG=C
并重

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 repo中尝试此操作,因为它可能损坏git的内部存储。
mgold 2014年

11
@mgold太晚了,grrr; /
kenorb 2015年

3
为了明确起见,可以在git repo的子文件夹中运行它,而不是在包含git repo作为后代的任何文件夹中运行,即.git,无论嵌套的深度如何,都不要在任何包含目录的文件夹中运行。
Illya Moskvin '16

将此答案与find . -not \( -name .svn -prune -o -name .git -prune \) -type f -print0 | xargs -0 perl -pi -e 's/ +$//'
@deepwell

1
可能有更好的方法,但是我通过将git repo克隆到一个单独的文件夹中,然后通过这样做来恢复git repo,然后rsync -rv --exclude=.git repo/ repo2/在本地存储中repo也进行了(未损坏的)更改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)

Mat专门针对Git仓库的解决方案,它使用-I选项git grep来跳过Git认为是二进制的文件:

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

3
所以我真的很喜欢这个git解决方案。它确实应该在顶部。我不想保存回车。但是我比2010
总和

我的git抱怨-e表达式为空,但使用-e'。*'效果很好
muirbot 2014年

@okor在GNU中sed,后缀选项-i可选的,但在BSD中sed则不是。严格来说,这里绝对没有必要,因此我将其删除。
2014年

24

在Bash中:

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

注意:如果您使用的是.git存储库,请尝试添加:-not -iwholename '.git'


这样会为找到的每个文件生成此类错误。sed:1:“ dir / file.txt”:命令a期望\后跟文本
iamjwc

替换“;” 用\; 应该管用。(也严格不需要在{}周围加上引号)。
2008年

4
要删除所有空格而不只是空格,您应该在sed正则表达式中用[:space:]替换空格字符。
WMR

另一个注意事项:这仅适用于sed版本> = 4,较小的版本不支持就地编辑。
WMR

1
这打破了我的混蛋:(
CrabMan '17

14

在OSX 10.5 Leopard中,这对我有用,它不使用GNU sed或xargs。

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 2010年

如果您使用的是tcsh,则需要将双引号更改为单引号。否则,您将获得“非法变量名”。错误。
布兰登·福斯迪克

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'16

9

阿克就是做这种任务的。

它像grep一样工作,但不知道它会落入.svn,.git,.cvs等地方。

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

与使用find / grep跳过箍相比要容易得多。

大多数软件包管理器都可以使用Ack(作为ackack-grep)。

它只是一个Perl程序,因此它也有单文件版本,您可以下载并运行它。请参阅:确认安装


ack太好了 已经使用了很多年,并且在大多数发行版的几乎所有软件包存储库中都可用。
费利佩·阿尔瓦雷斯

8

ex

尝试使用Ex编辑器(Vim的一部分):

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

注意:对于递归(bash4和zsh),我们使用新的globlob选项**/*.*)。启用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" {} \;仅删除一个尾随空格,而不是全部。
卡尔·里希特

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 2015年

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"-type f则使用after 。

更新2:现在替换行尾的所有空格(也意味着制表符)


4
我不知道这是怎么回事,但这完全使我的git repo烦恼了,并弄乱了我的图像。人,要比我更小心!
mattalxndr 2011年

是的,它将破坏二进制文件。但是,它根本不应该接触您的git repo,因为它会跳过.git-folder内的任何内容。但是也许只有当您在同一个文件夹中时。
奥迪尼奥-费尔蒙

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

第一个注册一个git别名check-whitespace,该别名列出带有尾随空格的文件。第二个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次。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.