如何将制表符转换为一个目录的每个文件中的空格(可能递归)?
此外,是否有一种方法来设置每个制表符的空格数?
如何将制表符转换为一个目录的每个文件中的空格(可能递归)?
此外,是否有一种方法来设置每个制表符的空格数?
当前回答
您可以使用通常可用的pr命令(此处的手册页)。例如,要将制表符转换为四个空格,可以这样做:
pr -t -e=4 file > file.expanded
-t抑制头文件 -e=num将制表符扩展为num个空格
递归转换目录树中的所有文件,跳过二进制文件:
#!/bin/bash
num=4
shopt -s globstar nullglob
for f in **/*; do
[[ -f "$f" ]] || continue # skip if not a regular file
! grep -qI "$f" && continue # skip binary files
pr -t -e=$num "$f" > "$f.expanded.$$" && mv "$f.expanded.$$" "$f"
done
跳过二进制文件的逻辑来自这篇文章。
注意:
在git或svn repo中这样做可能是危险的 如果您的代码文件在字符串字面值中嵌入了空白制表符,那么这不是正确的解决方案
其他回答
从Gene的回答中收集最好的评论,到目前为止最好的解决方案是使用moreutils的海绵。
sudo apt-get install moreutils
# The complete one-liner:
find ./ -iname '*.java' -type f -exec bash -c 'expand -t 4 "$0" | sponge "$0"' {} \;
解释:
./从当前目录递归搜索 -iname是不区分大小写的匹配(对*.java和*.java都适用) Type -f只查找常规文件(没有目录、二进制文件或符号链接) -exec bash -c在子shell中为每个文件名执行以下命令,{} expand -t 4将所有tab扩展为4个空格 海绵吸收标准输入(从扩展)并写入文件(同一文件)*。
注意:*一个简单的文件重定向(> "$0")在这里不能工作,因为它会很快覆盖文件。
优点:保留所有原始文件权限,不使用中间的tmp文件。
简单地用sed替换是可以的,但不是最好的解决方案。如果制表符之间有“额外的”空格,替换后它们仍然在那里,因此页边距将是粗糙的。在行中间展开的制表符也不能正常工作。在bash中,我们可以说相反
find . -name '*.java' ! -type d -exec bash -c 'expand -t 4 "$0" > /tmp/e && mv /tmp/e "$0"' {} \;
将展开应用到当前目录树中的每个Java文件。如果目标是其他文件类型,则删除/替换name参数。正如其中一条评论提到的,在删除name或使用弱通配符时要非常小心。你可以很容易地破坏存储库和其他隐藏的文件。这就是为什么最初的答案是这样的:
在尝试这样做之前,您应该始终对树进行备份,以防出现错误。
在发现混合制表符和空格后,我使用style重新缩进所有的C/ c++代码。如果您愿意,它还可以强制使用特定的括号样式。
下载并运行以下脚本,递归地将纯文本文件中的硬选项卡转换为软选项卡。
在包含纯文本文件的文件夹中执行脚本。
#!/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;
没有人提到rpl?使用rpl可以替换任何字符串。 要将制表符转换为空格,
rpl -R -e "\t" " " .
非常简单。