如何将制表符转换为一个目录的每个文件中的空格(可能递归)?

此外,是否有一种方法来设置每个制表符的空格数?


当前回答

我的建议是使用:

find . -name '*.lua' -exec ex '+%s/\t/  /g' -cwq {} \;

评论:

Use in place editing. Keep backups in a VCS. No need to produce *.orig files. It's good practice to diff the result against your last commit to make sure this worked as expected, in any case. sed is a stream editor. Use ex for in place editing. This avoids creating extra temp files and spawning shells for each replacement as in the top answer. WARNING: This messes with all tabs, not only those used for indentation. Also it does not do context aware replacement of tabs. This was sufficient for my use case. But might not be acceptable for you. EDIT: An earlier version of this answer used find|xargs instead of find -exec. As pointed out by @gniourf-gniourf this leads to problems with spaces, quotes and control chars in file names cf. Wheeler.

其他回答

下载并运行以下脚本,递归地将纯文本文件中的硬选项卡转换为软选项卡。

在包含纯文本文件的文件夹中执行脚本。

#!/bin/bash

find . -type f -and -not -path './.git/*' -exec grep -Iq . {} \; -and -print | while read -r file; do {
    echo "Converting... "$file"";
    data=$(expand --initial -t 4 "$file");
    rm "$file";
    echo "$data" > "$file";
}; done;

Git存储库友好方法

git-tab-to-space() (
  d="$(mktemp -d)"
  git grep --cached -Il '' | grep -E "${1:-.}" | \
    xargs -I'{}' bash -c '\
    f="${1}/f" \
    && expand -t 4 "$0" > "$f" && \
    chmod --reference="$0" "$f" && \
    mv "$f" "$0"' \
    '{}' "$d" \
  ;
  rmdir "$d"
)

操作当前目录下的所有文件:

git-tab-to-space

仅作用于C或c++文件:

git-tab-to-space '\.(c|h)(|pp)$'

您可能特别需要这个,因为那些讨厌的makefile需要选项卡。

命令git grep——cached -Il ":

只列出被跟踪的文件,所以.git中没有任何内容 不包括目录、二进制文件(将被损坏)和符号链接(将被转换为常规文件)

如在解释:如何列出所有文本(非二进制)文件在一个git仓库?

chmod——reference保持文件权限不变:https://unix.stackexchange.com/questions/20645/clone-ownership-and-permissions-from-another-file不幸的是,我找不到一个简洁的POSIX替代方案。

如果你的代码库有一个疯狂的想法,允许在字符串中使用功能原始制表符,使用:

expand -i

然后一个接一个地浏览所有非行开头的制表符,你可以列出:是否可能为制表符git grep ?

在Ubuntu 18.04上测试。

在其他答案中建议的使用expand似乎是仅用于此任务的最合乎逻辑的方法。

也就是说,它也可以用Bash和Awk来完成,以防你想在它的同时做一些其他的修改。

如果使用Bash 4.0或更高版本,shopt内置的globstar可以使用**进行递归搜索。

在GNU Awk 4.1或更高版本中,sed可以像“inplace”一样修改文件:

shopt -s globstar
gawk -i inplace '{gsub("\t","    ")}1' **/*.ext

如果你想设置每个制表符的空格数:

gawk -i inplace -v n=4 'BEGIN{for(i=1;i<=n;i++) c=c" "}{gsub("\t",c)}1' **/*.ext

使用反斜杠转义sed。

在linux上:

将所有*.txt文件中的所有制表符替换为1个连字符: Sed -i $'s/\t/-/g' *.txt 将所有*.txt文件中的所有制表符替换为1个空格: Sed -i $'s/\t/ /g' *.txt 将所有*.txt文件中的所有制表符替换为4个空格: Sed -i $'s/\t/ /g' *.txt

在mac电脑上:

将所有*.txt文件中的所有制表符替换为4个空格: Sed -i " $'s/\t/ /g' *.txt

我的建议是使用:

find . -name '*.lua' -exec ex '+%s/\t/  /g' -cwq {} \;

评论:

Use in place editing. Keep backups in a VCS. No need to produce *.orig files. It's good practice to diff the result against your last commit to make sure this worked as expected, in any case. sed is a stream editor. Use ex for in place editing. This avoids creating extra temp files and spawning shells for each replacement as in the top answer. WARNING: This messes with all tabs, not only those used for indentation. Also it does not do context aware replacement of tabs. This was sufficient for my use case. But might not be acceptable for you. EDIT: An earlier version of this answer used find|xargs instead of find -exec. As pointed out by @gniourf-gniourf this leads to problems with spaces, quotes and control chars in file names cf. Wheeler.