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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/149057/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 17:42:34  来源:igfitidea点击:

How to remove trailing whitespace of all files recursively?

bashwhitespace

提问by iamjwc

How can you remove all of the trailing whitespace of an entire project? Starting at a root directory, and removing the trailing whitespace from all files in all folders.

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

Also, I want to to be able to modify the file directly, and not just print everything to stdout.

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

回答by deepwell

Here is an OS X >= 10.6 Snow Leopard solution.

这是一个 OS X >= 10.6 Snow Leopard 解决方案。

It Ignores .git and .svn foldersand their contents. Also it won't leave a backup file.

它忽略 .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:]]*$//"

回答by Sec

Use:

用:

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

if you don't want the ".bak" files generated:

如果您不想生成“.bak”文件:

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

as a zsh user, you can omit the call to find, and instead use:

作为 zsh 用户,您可以省略 find 调用,而是使用:

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

Note: To prevent destroying .gitdirectory, try adding: -not -iwholename '*.git*'.

注意:为防止破坏.git目录,请尝试添加:-not -iwholename '*.git*'.

回答by l0b0

Two alternative approaches which also work with DOS newlines(CR/LF) and do a pretty good job at avoiding binary files:

两种替代方法也适用于DOS 换行符(CR/LF)并且在避免二进制文件方面做得很好:

Generic solutionwhich checks that the MIME type starts with text/:

检查 MIME 类型是否以以下开头的通用解决方案text/

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

Git repository-specificsolutionby Mat which uses the -Ioption of git grepto skip files which Git considers to be binary:

Mat 的Git 存储库特定解决方案,它使用 的-I选项git grep来跳过 Git 认为是二进制的文件:

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

回答by Adam Rosenfield

In Bash:

在 Bash 中:

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

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

Note: If you're using .gitrepository, try adding: -not -iwholename '.git'.

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

回答by pojo

This worked for me in OSX 10.5 Leopard, which does not use GNU sed or xargs.

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

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

Just be careful with this if you have files that need to be excluded (I did)!

如果您有需要排除的文件(我做到了),请注意这一点!

You can use -prune to ignore certain directories or files. For Python files in a git repository, you could use something like:

您可以使用 -prune 忽略某些目录或文件。对于 git 存储库中的 Python 文件,您可以使用以下内容:

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

回答by jbbuckley

Ack was made for this kind of task.

Ack 就是为这种任务而制作的。

It works just like grep, but knows not to descend into places like .svn, .git, .cvs, etc.

它的工作方式与 grep 类似,但知道不会下降到 .svn、.git、.cvs 等位置。

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

Much easier than jumping through hoops with find/grep.

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

Ack is available via most package managers (as either ackor ack-grep).

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

It's just a Perl program, so it's also available in a single-file version that you can just download and run. See: Ack Install

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

回答by kenorb

ex

ex

Try using Ex editor(part of Vim):

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

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

Note: For recursion (bash4 & zsh), we use a new globbing option(**/*.*). Enable by shopt -s globstar.

注意:对于递归(bash4 和 zsh),我们使用新的通配选项( **/*.*)。通过 启用shopt -s globstar

You may add the following function into your .bash_profile:

您可以将以下功能添加到您的.bash_profile:

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

sed

sed

For using sed, check: How to remove trailing whitespaces with sed?

对于使用sed,请检查:如何使用 sed 删除尾随空格?

find

find

Find the following script (e.g. remove_trail_spaces.sh) for removing trailing whitespaces from the files:

找到以下脚本(例如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

Run this script from the directory which you want to scan. On OSX at the end, it will remove all the files ending with .bak.

从要扫描的目录运行此脚本。最后在 OSX 上,它将删除所有以.bak.

Or just:

要不就:

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

which is recommended way by Spring Framework Code Style.

这是Spring Framework Code Style推荐的方式。

回答by Jesper R?nn-Jensen

I ended up not using find and not creating backup files.

我最终没有使用 find 并且没有创建备份文件。

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

Depending on the depth of the file tree, this (shorter version) may be sufficient for your needs.

根据文件树的深度,此(较短版本)可能足以满足您的需要。

NOTE this also takes binary files, for instance.

注意这也需要二进制文件,例如。

回答by ChicagoBob

Instead of excluding files, here is a variation of the above the explicitly white lists the files, based on file extension, that you want to strip, feel free to season to taste:

这里不是排除文件,而是上面明确的白名单文件的变体,基于文件扩展名,你想删除,随意调味:

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

回答by odinho - Velmont

I ended up running this, which is a mix between pojo and adams version.

我最终运行了这个,它是 pojo 和 adams 版本之间的混合。

It will clean both trailing whitespace, and also another form of trailing whitespace, the carriage return:

它将清除尾随空格以及另一种形式的尾随空格,即回车:

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

It won't touch the .git folder if there is one.

如果有,它不会触及 .git 文件夹。

Edit: Made it a bit safer after the comment, not allowing to take files with ".git" or ".svn" in it. But beware, it willtouch binary files if you've got some. Use -iname "*.py" -or -iname "*.php"after -type fif you only want it to touch e.g. .py and .php-files.

编辑:在评论后让它更安全一点,不允许在其中使用“.git”或“.svn”的文件。但要注意,如果你有一些二进制文件,它接触到二进制文件。如果您只希望它接触例如 .py 和 .php 文件,请使用-iname "*.py" -or -iname "*.php"after -type f

Update 2: It now replaces all kinds of spaces at end of line (which means tabs as well)

更新 2:它现在替换行尾的各种空格(这也意味着制表符)