Gen*_*ene 328
简单的替换sed是可以的,但不是最好的解决方案.如果标签之间存在"额外"空格,则替换后它们仍然存在,因此边距将是不规则的.在行中间展开的选项卡也无法正常工作.在bash,我们可以说
find . -name '*.java' ! -type d -exec bash -c 'expand -t 4 "$0" > /tmp/e && mv /tmp/e "$0"' {} \;
Run Code Online (Sandbox Code Playgroud)
应用于expand当前目录树中的每个Java文件.-name如果您要定位其他一些文件类型,请删除/替换参数.正如其中一条评论所提到的,在删除-name或使用弱通配符时要非常小心.您可以轻松地破坏存储库和其他隐藏文件.这就是为什么最初的答案包括:
在尝试这样的事情之前,您应该始终制作树的备份副本,以防出现问题.
kev*_*kev 186
尝试使用命令行工具expand.
expand -i -t 4 input | sponge output
Run Code Online (Sandbox Code Playgroud)
哪里
最后,您可以gexpand在coreutils使用Homebrew(brew install coreutils)安装后在OSX上使用.
Mar*_*ett 66
警告:这会破坏你的回购.
这将损坏的二进制文件,包括那些在
svn,.git!使用前请阅读评论!
find . -type f -exec sed -i.orig 's/\t/ /g' {} +
原始文件保存为[filename].orig.
缺点:
not*_*bit 26
从收集的最好注解基因的答案,目前最好的解决办法,是通过使用sponge从moreutils.
sudo apt-get install moreutils
# The complete one-liner:
find ./ -iname '*.java' -type f -exec bash -c 'expand -t 4 "$0" | sponge "$0"' {} \;
Run Code Online (Sandbox Code Playgroud)
说明:
./ 从当前目录递归搜索-iname是一个不区分大小写的匹配(对于两者*.java和*.JAVA喜欢)type -f 只查找常规文件(没有目录,二进制文件或符号链接)-exec bash -c 在子shell中为每个文件名执行以下命令, {}expand -t 4 将所有TAB扩展为4个空格sponge吸收标准输入(从expand)并写入文件(同一个)*.注意:*简单的文件重定向(> "$0")在这里不起作用,因为它会过快地覆盖文件.
优点:保留所有原始文件权限,不tmp使用任何中间文件.
e9t*_*e9t 16
使用反斜杠转义sed.
在linux上:
在所有*.txt文件中,用1个连字符替换所有选项卡:
sed -i $'s/\t/-/g' *.txt
Run Code Online (Sandbox Code Playgroud)在所有*.txt文件中,用1个空格替换所有选项卡:
sed -i $'s/\t/ /g' *.txt
Run Code Online (Sandbox Code Playgroud)在所有*.txt文件中替换所有4个空格的选项卡:
sed -i $'s/\t/ /g' *.txt
Run Code Online (Sandbox Code Playgroud)在mac上:
在所有*.txt文件中替换所有4个空格的选项卡:
sed -i '' $'s/\t/ /g' *.txt
Run Code Online (Sandbox Code Playgroud)您可以使用一般可用的pr命令(此处的手册页)。例如,要将制表符转换为四个空格,请执行以下操作:
pr -t -e=4 file > file.expanded
Run Code Online (Sandbox Code Playgroud)
-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
Run Code Online (Sandbox Code Playgroud)
跳过二进制文件的逻辑来自这篇文章。
笔记:
我喜欢上面递归应用程序的“查找”示例。为了使其成为非递归的,仅更改当前目录中与通配符匹配的文件,shell glob 扩展对于少量文件就足够了:
ls *.java | awk '{print "expand -t 4 ", $0, " > /tmp/e; mv /tmp/e ", $0}' | sh -v
Run Code Online (Sandbox Code Playgroud)
如果你想它沉默之后,你相信它的作品,只是降-v的sh末命令。
当然,您可以在第一个命令中选择任何一组文件。例如,以如下受控方式仅列出特定的子目录(或目录):
ls mod/*/*.php | awk '{print "expand -t 4 ", $0, " > /tmp/e; mv /tmp/e ", $0}' | sh
Run Code Online (Sandbox Code Playgroud)
或者反过来运行 find(1) 并结合一些深度参数等:
find mod/ -name '*.php' -mindepth 1 -maxdepth 2 | awk '{print "expand -t 4 ", $0, " > /tmp/e; mv /tmp/e ", $0}' | sh
Run Code Online (Sandbox Code Playgroud)
如何将目录的每个文件中的制表符转换为空格(可能是递归的)?
这通常不是您想要的。
您想对 png 图像执行此操作吗?PDF文件?.git 目录?你的
Makefile(需要标签)?一个 5GB 的 SQL 转储?
理论上,您可以将大量排除选项传递给find您正在使用的任何其他选项;但这很脆弱,一旦添加其他二进制文件就会损坏。
你想要的,至少是:
expand这样做,sed
不这样做)。据我所知,没有“标准”的 Unix 实用程序可以做到这一点,而且使用单行 shell 也不是很容易,因此需要一个脚本。
不久前,我创建了一个名为sanitize_files的小脚本
,它正是这样做的。它还修复了一些其他常见的东西,例如替换\r\n为\n,添加尾随\n等。
您可以在下面找到一个没有额外功能和命令行参数的简化脚本,但我建议您使用上面的脚本,因为它比这篇文章更有可能收到错误修正和其他更新。
我还想指出,为了回应这里的其他一些答案,使用 shell globbing不是一种可靠的方法,因为迟早你会得到比适合的更多的文件ARG_MAX(在现代Linux系统是128K,这可能看起来很多,但它迟早是不
足够的)。
#!/usr/bin/env python
#
# http://code.arp242.net/sanitize_files
#
import os, re, sys
def is_binary(data):
return data.find(b'\000') >= 0
def should_ignore(path):
keep = [
# VCS systems
'.git/', '.hg/' '.svn/' 'CVS/',
# These files have significant whitespace/tabs, and cannot be edited
# safely
# TODO: there are probably more of these files..
'Makefile', 'BSDmakefile', 'GNUmakefile', 'Gemfile.lock'
]
for k in keep:
if '/%s' % k in path:
return True
return False
def run(files):
indent_find = b'\t'
indent_replace = b' ' * indent_width
for f in files:
if should_ignore(f):
print('Ignoring %s' % f)
continue
try:
size = os.stat(f).st_size
# Unresolvable symlink, just ignore those
except FileNotFoundError as exc:
print('%s is unresolvable, skipping (%s)' % (f, exc))
continue
if size == 0: continue
if size > 1024 ** 2:
print("Skipping `%s' because it's over 1MiB" % f)
continue
try:
data = open(f, 'rb').read()
except (OSError, PermissionError) as exc:
print("Error: Unable to read `%s': %s" % (f, exc))
continue
if is_binary(data):
print("Skipping `%s' because it looks binary" % f)
continue
data = data.split(b'\n')
fixed_indent = False
for i, line in enumerate(data):
# Fix indentation
repl_count = 0
while line.startswith(indent_find):
fixed_indent = True
repl_count += 1
line = line.replace(indent_find, b'', 1)
if repl_count > 0:
line = indent_replace * repl_count + line
data = list(filter(lambda x: x is not None, data))
try:
open(f, 'wb').write(b'\n'.join(data))
except (OSError, PermissionError) as exc:
print("Error: Unable to write to `%s': %s" % (f, exc))
if __name__ == '__main__':
allfiles = []
for root, dirs, files in os.walk(os.getcwd()):
for f in files:
p = '%s/%s' % (root, f)
if do_add:
allfiles.append(p)
run(allfiles)
Run Code Online (Sandbox Code Playgroud)
我的建议是使用:
find . -name '*.lua' -exec ex '+%s/\t/ /g' -cwq {} \;
Run Code Online (Sandbox Code Playgroud)
注释:
sed是一个流编辑器。使用ex就地编辑了。这避免了为每个替换创建额外的临时文件和生成外壳,如最佳答案。find|xargs代替find -exec. 正如@gniourf-gniourf 所指出的,这会导致文件名中的空格、引号和控制字符出现问题 cf. 惠勒。为此,您可以使用findwithtabs-to-spaces包。
首先,安装 tabs-to-spaces
npm install -g tabs-to-spaces
Run Code Online (Sandbox Code Playgroud)
然后,从项目的根目录运行此命令;
find . -name '*' -exec t2s --spaces 2 {} \;
Run Code Online (Sandbox Code Playgroud)
这将在每个文件tab中用 2替换每个字符spaces。
| 归档时间: |
|
| 查看次数: |
141438 次 |
| 最近记录: |