Как я могу конвертировать вкладки в пробелы в каждом файле каталога (возможно, рекурсивно)?
Кроме того, существует ли способ задать количество пробелов на вкладку?
Как я могу конвертировать вкладки в пробелы в каждом файле каталога (возможно, рекурсивно)?
Кроме того, существует ли способ задать количество пробелов на вкладку?
Предупреждение: это нарушит ваше репо.
Этот приведет к повреждению двоичных файлов, в том числе в
svn,.git! Прочитайте комментарии перед использованием!
 find . -type f -exec sed -i.orig 's/\t/ /g' {} +
Исходный файл сохраняется как [filename].orig.
Downsides:
Простая замена с помощью sed в порядке, но не наилучшим возможным решением. Если между вкладками есть "лишние" пробелы, они все равно будут присутствовать после замены, поэтому поля будут оборваны. Вкладки, развернутые в середине строк, также будут работать неправильно. В bash мы можем сказать вместо этого
find . -name '*.java' ! -type d -exec bash -c 'expand -t 4 "$0" > /tmp/e && mv /tmp/e "$0"' {} \;
применить expand к каждому файлу Java в текущем дереве каталогов. Удалите/замените аргумент -name, если вы настроили таргетинг на другие типы файлов. Как отмечается в одном из замечаний, будьте очень осторожны при удалении -name или использовании слабого шаблона. Вы можете легко сбрасывать репозиторий и другие скрытые файлы без намерения. Вот почему исходный ответ включал это:
Вы всегда должны делать резервную копию дерева, прежде чем пытаться что-то вроде этого, если что-то пойдет не так.
Попробуйте инструмент командной строки expand.
expand -i -t 4 input | sponge output
где
-i используется для расширения только ведущих вкладок в каждой строке;-t 4 означает, что каждая вкладка будет преобразована в 4 символа пробела (по умолчанию 8).sponge находится из moreutils и избегает очистки входного файла.Наконец, вы можете использовать gexpand в OSX после установки coreutils с помощью Homebrew (brew install coreutils).
Использовать обратную косую черту sed.
В linux:
Замените все вкладки 1 дефисом inplace во всех файлах *.txt:
sed -i $'s/\t/-/g' *.txt
Замените все вкладки на 1 место внутри, во всех *.txt файлах:
sed -i $'s/\t/ /g' *.txt
Замените все вкладки четырьмя пробелами внутри всех *.txt файлов:
sed -i $'s/\t/    /g' *.txt
На mac:
Замените все вкладки четырьмя пробелами внутри всех *.txt файлов:
sed -i '' $'s/\t/    /g' *.txt
Собирая лучшие комментарии от Ответ на гены, лучшим решением на сегодняшний день является использование 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"' {} \;
Объяснение:
./ - это рекурсивно поиск из текущего каталога-iname - это нечувствительное к регистру совпадение (для *.java и *.java)type -f находит только обычные файлы (без каталогов, двоичных файлов или символических ссылок).-exec bash -c выполните следующие команды в подоболочке для каждого имени файла, {}expand -t 4 расширяет все TAB до 4 пробеловsponge впитайте стандартный ввод (из expand) и напишите в файл (тот же) *.  ПРИМЕЧАНИЕ: * Простое перенаправление файлов (> "$0") здесь не будет работать, потому что слишком быстро перезапишет файл.
  Преимущество: все исходные разрешения файлов сохраняются и не используются промежуточные файлы tmp.
Мне нравится пример "найти" выше для рекурсивного приложения. Чтобы адаптировать его к нерекурсивному, только изменение файлов в текущем каталоге, которое соответствует шаблону, расширение оболочки оболочки может быть достаточным для небольших объемов файлов:
ls *.java | awk '{print "expand -t 4 ", $0, " > /tmp/e; mv /tmp/e ", $0}' | sh -v
Если вы хотите, чтобы он молчал, когда вы верите, что он работает, просто отпустите -v в команде sh в конце.
Конечно, вы можете выбрать любой набор файлов в первой команде. Например, перечислите только определенный подкаталог (или каталоги) таким образом:
ls mod/*/*.php | awk '{print "expand -t 4 ", $0, " > /tmp/e; mv /tmp/e ", $0}' | sh
Или, в свою очередь, запустите find (1) с некоторой комбинацией параметров глубины и т.д.:
find mod/ -name '*.php' -mindepth 1 -maxdepth 2 | awk '{print "expand -t 4 ", $0, " > /tmp/e; mv /tmp/e ", $0}' | sh
Как конвертировать вкладки в пробелы в каждом файле каталога (возможно рекурсивно)?
Обычно это не, что вы хотите.
Вы хотите сделать это для png-изображений? PDF файлы? Каталог .git? Ваш
Makefile (для чего нужны вкладки)? 5-мегабайтный SQL-дамп?
Вы могли бы теоретически передать множество опций исключения для find или что-то еще
иначе вы используете; но это хрупко и будет разорваться, как только вы добавите другое
двоичные файлы.
Что вы хотите, по крайней мере:
expand делает это, sed
не делает).Насколько мне известно, не существует "стандартной" утилиты Unix, которая может это сделать, и это не очень просто сделать с однострочным оболочкой, поэтому нужен script.
Некоторое время назад я создал немного script, называемый
sanitize_files, который точно
что. Он также фиксирует некоторые другие распространенные вещи, такие как замена \r\n на \n,
добавление завершающего \n и т.д.
Вы можете найти упрощенный script без дополнительных функций и аргументов командной строки ниже, но я рекомендуем использовать вышеприведенный script, поскольку он скорее получит исправления и другой обновлен, чем этот пост.
Я также хотел бы отметить, что в ответ на некоторые другие ответы здесь,
что использование 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 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)
Я использовал astyle для повторного ввода всего кода на C/С++ после поиска смешанных вкладок и пробелов. У него также есть опции, чтобы форсировать особый стиль фигурной скобки, если хотите.
Моя рекомендация:
find . -name '*.lua' -exec ex '+%s/\t/  /g' -cwq {} \;
Комментарии:
sed - редактор потока. Используйте ex для редактирования на месте. Это позволяет избежать создания дополнительных временных файлов и нерестовых оболочек для каждой замены, как в верхнем ответе.find|xargs вместо find -exec. Как указано в @gniourf-gniourf, это приводит к проблемам с пробелами, кавычками и контрольными символами в именах файлов ср. Wheeler.Чтобы преобразовать все файлы Java рекурсивно в каталог, чтобы использовать 4 пробела вместо закладки:
find . -type f -name *.java -exec bash -c 'expand -t 4 {} > /tmp/stuff;mv /tmp/stuff {}' \;
Загрузите и запустите следующий script, чтобы рекурсивно преобразовать жесткие вкладки в мягкие вкладки в текстовые файлы.
Выполните script из папки, содержащей текстовые файлы.
#!/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
Логика для пропуска двоичных файлов от этого сообщения.
Примечание:
Для этого можно использовать vim:
find -type f \( -name '*.css' -o -name '*.html' -o -name '*.js' -o -name '*.php' \) -execdir vim -c retab -c wq {} \;
Как заявил Carpetsmoker, он будет retab в соответствии с вашими настройками vim. И моделирует файлы, если они есть. Кроме того, он заменит вкладки не только в начале строк. Это не то, что вы обычно хотите. Например, у вас могут быть литералы, содержащие вкладки.
Если вы хотите заменить вкладки на пробелы, например, файлы *.c и *.h, следующая команда - лучшая:
find . -name "*.c" -o -name "*.h" | xargs -IFILE -t bash -c " expand -t 4 FILE > tmp ; cat tmp > FILE"
Тогда rm -f tmp
Вы можете использовать find с tabs-to-spaces для этого.
Сначала установите tabs-to-spaces
npm install -g tabs-to-spaces
тогда запустите эту команду из корневого каталога вашего проекта;
find . -name '*' -exec t2s --spaces 2 {} \;
Это заменит каждый символ tab на 2 spaces в каждом файле.
Преобразование вкладок в пространство только в файлах ".lua" [вкладки → 2 пробела]
find . -iname "*.lua" -exec sed -i "s#\t#  #g" '{}' \;
Использование expand, как было предложено в других ответах, кажется наиболее логичным для этой задачи.
Тем не менее, это также можно сделать с помощью Bash и Awk, если вы захотите сделать некоторые другие модификации вместе с ним.
При использовании Bash 4.0 или выше shopt builtin 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
Используйте vim-way:
$ ex +'bufdo retab' -cxa **/*.*
globstar (**) для рекурсии, активируйте shopt -s globstar.**/*.c.Чтобы изменить tabstop, добавьте +'set ts=2'.
Однако нижняя сторона - это замена вкладок внутри строк.
Итак, для немного лучшего решения (с помощью замены) попробуйте:
$ ex -s +'bufdo %s/^\t\+/  /ge' -cxa **/*.*
Или с помощью утилиты ex editor + expand:
$ ex -s +'bufdo!%!expand -t2' -cxa **/*.*
Для конечных пробелов см.: Как удалить конечные пробелы для нескольких файлов?
Вы можете добавить следующую функцию в свой .bash_profile:
# Convert tabs to spaces.
# Usage: retab *.*
# See: https://stackoverflow.com/q/11094383/55075
retab() {
  ex +'set ts=2' +'bufdo retab' -cxa $*
}
Если вы не против использования notepad ++ или подобного программного обеспечения, откройте все упомянутые файлы в блокноте ++, затем перейдите на вкладку замены (shortcut ctrl + h)
выберите регулярное выражение или расширенный режим поиска, теперь он отображает \t, помещает его в поиск и помещает любое количество пробелов, которое вы хотите заменить, щелкните по замене всех открытых документов.
заменить вкладку пробелом в блокноте ++
Существует также альтернатива, которая может лучше соответствовать вашим потребностям, вы можете сделать это на вкладке "Найти файлы", выбрать каталог и выбрать определенные файлы с помощью фильтра типов, а остальные - как раньше.