如何将制表符转换为一个目录的每个文件中的空格(可能递归)?
此外,是否有一种方法来设置每个制表符的空格数?
如何将制表符转换为一个目录的每个文件中的空格(可能递归)?
此外,是否有一种方法来设置每个制表符的空格数?
当前回答
下载并运行以下脚本,递归地将纯文本文件中的硬选项卡转换为软选项卡。
在包含纯文本文件的文件夹中执行脚本。
#!/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;
其他回答
您可以使用通常可用的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中这样做可能是危险的 如果您的代码文件在字符串字面值中嵌入了空白制表符,那么这不是正确的解决方案
在发现混合制表符和空格后,我使用style重新缩进所有的C/ c++代码。如果您愿意,它还可以强制使用特定的括号样式。
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上测试。
警告:这会破坏你的回购。 这将破坏二进制文件,包括那些在svn, .git!使用前请阅读评论!
找到。-iname '*.java' -type f -exec sed -i。/\t/ /g' {} +
原始文件保存为[filename]. trans。
将'*.java'替换为您正在寻找的文件类型的文件结尾。这样可以防止二进制文件的意外损坏。
缺点:
将替换文件中的所有制表符。 如果在这个目录中有一个5GB的SQL转储,将花费很长时间。
从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文件。